aboutsummaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/LPdir_nyi.c56
-rw-r--r--crypto/LPdir_unix.c9
-rw-r--r--crypto/LPdir_vms.c207
-rw-r--r--crypto/LPdir_win.c214
-rw-r--r--crypto/LPdir_win32.c41
-rw-r--r--crypto/LPdir_wince.c44
-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.pl157
-rw-r--r--crypto/aes/asm/aest4-sparcv9.pl12
-rwxr-xr-xcrypto/aes/asm/aesv8-armx.pl2690
-rw-r--r--crypto/aes/asm/bsaes-armv7.pl59
-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.info156
-rw-r--r--crypto/alphacpuid.pl256
-rw-r--r--crypto/aria/aria.c34
-rwxr-xr-xcrypto/arm64cpuid.pl18
-rw-r--r--crypto/arm_arch.h54
-rw-r--r--crypto/armcap.c51
-rw-r--r--crypto/armv4cpuid.pl14
-rw-r--r--crypto/asn1/a_bitstr.c61
-rw-r--r--crypto/asn1/a_d2i_fp.c76
-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.c61
-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.c21
-rw-r--r--crypto/asn1/a_strnid.c23
-rw-r--r--crypto/asn1/a_time.c102
-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.c162
-rw-r--r--crypto/asn1/ameth_lib.c86
-rw-r--r--crypto/asn1/asn1_err.c154
-rw-r--r--crypto/asn1/asn1_gen.c87
-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_parse.c (renamed from crypto/asn1/asn1_par.c)81
-rw-r--r--crypto/asn1/asn_mime.c197
-rw-r--r--crypto/asn1/asn_moid.c14
-rw-r--r--crypto/asn1/asn_mstbl.c22
-rw-r--r--crypto/asn1/asn_pack.c14
-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.c168
-rw-r--r--crypto/asn1/tasn_fre.c58
-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.c84
-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.c59
-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/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.c291
-rw-r--r--crypto/bio/bio_addr.c (renamed from crypto/bio/b_addr.c)94
-rw-r--r--crypto/bio/bio_cb.c74
-rw-r--r--crypto/bio/bio_dump.c (renamed from crypto/bio/b_dump.c)37
-rw-r--r--crypto/bio/bio_err.c75
-rw-r--r--crypto/bio/bio_lib.c376
-rw-r--r--crypto/bio/bio_local.h13
-rw-r--r--crypto/bio/bio_meth.c8
-rw-r--r--crypto/bio/bio_print.c (renamed from crypto/bio/b_print.c)47
-rw-r--r--crypto/bio/bio_sock.c (renamed from crypto/bio/b_sock.c)106
-rw-r--r--crypto/bio/bio_sock2.c (renamed from crypto/bio/b_sock2.c)82
-rw-r--r--crypto/bio/bss_acpt.c51
-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.c11
-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.pod241
-rw-r--r--crypto/bn/asm/alpha-mont.pl327
-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.pl412
-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.c110
-rw-r--r--crypto/bn/bn_blind.c33
-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.c152
-rw-r--r--crypto/bn/bn_exp2.c4
-rw-r--r--crypto/bn/bn_gcd.c16
-rw-r--r--crypto/bn/bn_gf2m.c123
-rw-r--r--crypto/bn/bn_intern.c22
-rw-r--r--crypto/bn/bn_kron.c2
-rw-r--r--crypto/bn/bn_lib.c111
-rw-r--r--crypto/bn/bn_local.h94
-rw-r--r--crypto/bn/bn_mod.c26
-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.c275
-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.c255
-rw-r--r--crypto/bn/bn_recp.c10
-rw-r--r--crypto/bn/bn_rsa_fips186_4.c367
-rw-r--r--crypto/bn/bn_shift.c14
-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.c614
-rw-r--r--crypto/bn/rsaz_exp.c2
-rw-r--r--crypto/bn/rsaz_exp.h21
-rw-r--r--crypto/bn/rsaz_exp_x2.c571
-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.info141
-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.pl293
-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.c923
-rw-r--r--crypto/cmp/cmp_ctx.c1173
-rw-r--r--crypto/cmp/cmp_err.c181
-rw-r--r--crypto/cmp/cmp_hdr.c369
-rw-r--r--crypto/cmp/cmp_http.c106
-rw-r--r--crypto/cmp/cmp_local.h933
-rw-r--r--crypto/cmp/cmp_msg.c1180
-rw-r--r--crypto/cmp/cmp_protect.c334
-rw-r--r--crypto/cmp/cmp_server.c665
-rw-r--r--crypto/cmp/cmp_status.c317
-rw-r--r--crypto/cmp/cmp_util.c286
-rw-r--r--crypto/cmp/cmp_vfy.c855
-rw-r--r--crypto/cms/build.info2
-rw-r--r--crypto/cms/cms_asn1.c35
-rw-r--r--crypto/cms/cms_att.c33
-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.c417
-rw-r--r--crypto/cms/cms_enc.c141
-rw-r--r--crypto/cms/cms_env.c754
-rw-r--r--crypto/cms/cms_err.c269
-rw-r--r--crypto/cms/cms_ess.c188
-rw-r--r--crypto/cms/cms_io.c55
-rw-r--r--crypto/cms/cms_kari.c220
-rw-r--r--crypto/cms/cms_lib.c302
-rw-r--r--crypto/cms/cms_local.h174
-rw-r--r--crypto/cms/cms_pwri.c127
-rw-r--r--crypto/cms/cms_rsa.c283
-rw-r--r--crypto/cms/cms_sd.c442
-rw-r--r--crypto/cms/cms_smime.c447
-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.c241
-rw-r--r--crypto/conf/conf_def.h12
-rw-r--r--crypto/conf/conf_err.c47
-rw-r--r--crypto/conf/conf_lib.c97
-rw-r--r--crypto/conf/conf_local.h8
-rw-r--r--crypto/conf/conf_mall.c13
-rw-r--r--crypto/conf/conf_mod.c286
-rw-r--r--crypto/conf/conf_sap.c32
-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.c172
-rw-r--r--crypto/core_namemap.c534
-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.c262
-rw-r--r--crypto/dh/dh_depr.c22
-rw-r--r--crypto/dh/dh_err.c59
-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.c409
-rw-r--r--crypto/dh/dh_lib.c153
-rw-r--r--crypto/dh/dh_local.h27
-rw-r--r--crypto/dh/dh_meth.c16
-rw-r--r--crypto/dh/dh_pmeth.c227
-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.c195
-rw-r--r--crypto/dsa/dsa_check.c133
-rw-r--r--crypto/dsa/dsa_depr.c31
-rw-r--r--crypto/dsa/dsa_err.c55
-rw-r--r--crypto/dsa/dsa_gen.c629
-rw-r--r--crypto/dsa/dsa_key.c150
-rw-r--r--crypto/dsa/dsa_lib.c358
-rw-r--r--crypto/dsa/dsa_local.h27
-rw-r--r--crypto/dsa/dsa_meth.c20
-rw-r--r--crypto/dsa/dsa_ossl.c169
-rw-r--r--crypto/dsa/dsa_pmeth.c94
-rw-r--r--crypto/dsa/dsa_prn.c12
-rw-r--r--crypto/dsa/dsa_sign.c198
-rw-r--r--crypto/dsa/dsa_vrf.c10
-rw-r--r--crypto/dso/dso_dl.c59
-rw-r--r--crypto/dso/dso_dlfcn.c47
-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/dso/dso_vms.c489
-rw-r--r--crypto/dso/dso_win32.c667
-rw-r--r--crypto/ebcdic.c2
-rwxr-xr-xcrypto/ec/asm/ecp_nistp521-ppc64.pl436
-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.h2
-rw-r--r--crypto/ec/curve448/arch_32/f_impl32.c (renamed from crypto/ec/curve448/arch_32/f_impl.c)16
-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.c430
-rw-r--r--crypto/ec/ec_backend.c836
-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.c317
-rw-r--r--crypto/ec/ec_key.c541
-rw-r--r--crypto/ec/ec_kmeth.c57
-rw-r--r--crypto/ec/ec_lib.c783
-rw-r--r--crypto/ec/ec_local.h562
-rw-r--r--crypto/ec/ec_mult.c144
-rw-r--r--crypto/ec/ec_oct.c58
-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.c201
-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.c263
-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.c1000
-rw-r--r--crypto/encode_decode/decoder_meth.c701
-rw-r--r--crypto/encode_decode/decoder_pkey.c466
-rw-r--r--crypto/encode_decode/encoder_err.c36
-rw-r--r--crypto/encode_decode/encoder_lib.c679
-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.c386
-rw-r--r--crypto/engine/README.md (renamed from crypto/engine/README)27
-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.c41
-rw-r--r--crypto/engine/eng_list.c97
-rw-r--r--crypto/engine/eng_local.h59
-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.c98
-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.ec81
-rw-r--r--crypto/err/openssl.txt2260
-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.c51
-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.c2888
-rw-r--r--crypto/evp/dh_ctrl.c346
-rw-r--r--crypto/evp/dh_support.c63
-rw-r--r--crypto/evp/digest.c903
-rw-r--r--crypto/evp/dsa_ctrl.c132
-rw-r--r--crypto/evp/e_aes.c1328
-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.c302
-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.c1273
-rw-r--r--crypto/evp/evp_err.c235
-rw-r--r--crypto/evp/evp_fetch.c703
-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.c157
-rw-r--r--crypto/evp/evp_pkey.c147
-rw-r--r--crypto/evp/evp_rand.c680
-rw-r--r--crypto/evp/evp_utils.c81
-rw-r--r--crypto/evp/exchange.c603
-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.c594
-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.c232
-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_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.c527
-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.c114
-rw-r--r--crypto/evp/p5_crpt.c93
-rw-r--r--crypto/evp/p5_crpt2.c288
-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.c2474
-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.c1664
-rw-r--r--crypto/evp/signature.c763
-rw-r--r--crypto/ex_data.c295
-rw-r--r--crypto/ffc/build.info8
-rw-r--r--crypto/ffc/ffc_backend.c130
-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.c124
-rw-r--r--crypto/ffc/ffc_params.c324
-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.c1449
-rw-r--r--crypto/http/http_err.c82
-rw-r--r--crypto/http/http_lib.c307
-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.c574
-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.c52
-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.c (renamed from crypto/evp/m_md5_sha1.c)70
-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.c223
-rw-r--r--crypto/mem_clr.c2
-rw-r--r--crypto/mem_dbg.c670
-rw-r--r--crypto/mem_sec.c211
-rw-r--r--crypto/mips_arch.h4
-rwxr-xr-xcrypto/modes/asm/aes-gcm-armv8_64.pl6097
-rw-r--r--crypto/modes/asm/aesni-gcm-x86_64.pl12
-rw-r--r--crypto/modes/asm/ghash-alpha.pl467
-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.pl43
-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.c188
-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.c122
-rw-r--r--crypto/params.c1319
-rw-r--r--crypto/params_dup.c235
-rw-r--r--crypto/params_from_text.c236
-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.c225
-rw-r--r--crypto/pem/pem_pkey.c454
-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.pl28
-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.pl12
-rw-r--r--crypto/perlasm/x86_64-support.pl51
-rwxr-xr-xcrypto/perlasm/x86_64-xlate.pl61
-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.c128
-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.c210
-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.c130
-rw-r--r--crypto/pkcs12/p12_npas.c27
-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.c33
-rw-r--r--crypto/pkcs7/pk7_doit.c427
-rw-r--r--crypto/pkcs7/pk7_lib.c290
-rw-r--r--crypto/pkcs7/pk7_local.h16
-rw-r--r--crypto/pkcs7/pk7_mime.c41
-rw-r--r--crypto/pkcs7/pk7_smime.c160
-rw-r--r--crypto/pkcs7/pkcs7err.c68
-rwxr-xr-xcrypto/poly1305/asm/poly1305-armv4.pl53
-rwxr-xr-xcrypto/poly1305/asm/poly1305-armv8.pl69
-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.pl1564
-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.pl20
-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.c787
-rw-r--r--crypto/property/property_err.c46
-rw-r--r--crypto/property/property_local.h55
-rw-r--r--crypto/property/property_parse.c763
-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.c382
-rw-r--r--crypto/provider_core.c2180
-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.c1353
-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.c44
-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.info49
-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.c788
-rw-r--r--crypto/rsa/rsa_asn1.c21
-rw-r--r--crypto/rsa/rsa_backend.c583
-rw-r--r--crypto/rsa/rsa_chk.c114
-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.c855
-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.c116
-rw-r--r--crypto/rsa/rsa_ossl.c203
-rw-r--r--crypto/rsa/rsa_pk1.c193
-rw-r--r--crypto/rsa/rsa_pmeth.c205
-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.c443
-rw-r--r--crypto/rsa/rsa_sp800_56b_gen.c449
-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.pl8
-rwxr-xr-xcrypto/sha/asm/keccak1600-avx512.pl8
-rwxr-xr-xcrypto/sha/asm/keccak1600-avx512vl.pl8
-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-alpha.pl329
-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.c155
-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.c189
-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.c111
-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.c650
-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.c120
-rw-r--r--crypto/threads_win.c264
-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.c423
-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.c188
-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.c34
-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.c107
-rw-r--r--crypto/x509/by_file.c110
-rw-r--r--crypto/x509/by_store.c298
-rw-r--r--crypto/x509/ext_dat.h27
-rw-r--r--crypto/x509/pcy_cache.c (renamed from crypto/x509v3/pcy_cache.c)35
-rw-r--r--crypto/x509/pcy_data.c (renamed from crypto/x509v3/pcy_data.c)14
-rw-r--r--crypto/x509/pcy_lib.c (renamed from crypto/x509v3/pcy_lib.c)6
-rw-r--r--crypto/x509/pcy_local.h (renamed from crypto/x509v3/pcy_local.h)54
-rw-r--r--crypto/x509/pcy_map.c (renamed from crypto/x509v3/pcy_map.c)18
-rw-r--r--crypto/x509/pcy_node.c (renamed from crypto/x509v3/pcy_node.c)66
-rw-r--r--crypto/x509/pcy_tree.c (renamed from crypto/x509v3/pcy_tree.c)156
-rw-r--r--crypto/x509/standard_exts.h80
-rw-r--r--crypto/x509/t_crl.c8
-rw-r--r--crypto/x509/t_req.c30
-rw-r--r--crypto/x509/t_x509.c198
-rw-r--r--crypto/x509/v3_addr.c (renamed from crypto/x509v3/v3_addr.c)161
-rw-r--r--crypto/x509/v3_admis.c (renamed from crypto/x509v3/v3_admis.c)45
-rw-r--r--crypto/x509/v3_admis.h (renamed from crypto/x509v3/v3_admis.h)6
-rw-r--r--crypto/x509/v3_akeya.c (renamed from crypto/x509v3/v3_akeya.c)2
-rw-r--r--crypto/x509/v3_akid.c (renamed from crypto/x509v3/v3_akey.c)114
-rw-r--r--crypto/x509/v3_asid.c (renamed from crypto/x509v3/v3_asid.c)87
-rw-r--r--crypto/x509/v3_bcons.c (renamed from crypto/x509v3/v3_bcons.c)13
-rw-r--r--crypto/x509/v3_bitst.c (renamed from crypto/x509v3/v3_bitst.c)18
-rw-r--r--crypto/x509/v3_conf.c (renamed from crypto/x509v3/v3_conf.c)233
-rw-r--r--crypto/x509/v3_cpols.c (renamed from crypto/x509v3/v3_cpols.c)104
-rw-r--r--crypto/x509/v3_crld.c (renamed from crypto/x509v3/v3_crld.c)79
-rw-r--r--crypto/x509/v3_enum.c (renamed from crypto/x509v3/v3_enum.c)6
-rw-r--r--crypto/x509/v3_extku.c (renamed from crypto/x509v3/v3_extku.c)15
-rw-r--r--crypto/x509/v3_genn.c (renamed from crypto/x509v3/v3_genn.c)4
-rw-r--r--crypto/x509/v3_ia5.c (renamed from crypto/x509v3/v3_ia5.c)17
-rw-r--r--crypto/x509/v3_info.c (renamed from crypto/x509v3/v3_info.c)34
-rw-r--r--crypto/x509/v3_int.c (renamed from crypto/x509v3/v3_int.c)10
-rw-r--r--crypto/x509/v3_ist.c152
-rw-r--r--crypto/x509/v3_lib.c (renamed from crypto/x509v3/v3_lib.c)25
-rw-r--r--crypto/x509/v3_ncons.c (renamed from crypto/x509v3/v3_ncons.c)205
-rw-r--r--crypto/x509/v3_pci.c (renamed from crypto/x509v3/v3_pci.c)51
-rw-r--r--crypto/x509/v3_pcia.c (renamed from crypto/x509v3/v3_pcia.c)2
-rw-r--r--crypto/x509/v3_pcons.c (renamed from crypto/x509v3/v3_pcons.c)18
-rw-r--r--crypto/x509/v3_pku.c (renamed from crypto/x509v3/v3_pku.c)6
-rw-r--r--crypto/x509/v3_pmaps.c (renamed from crypto/x509v3/v3_pmaps.c)20
-rw-r--r--crypto/x509/v3_prn.c (renamed from crypto/x509v3/v3_prn.c)18
-rw-r--r--crypto/x509/v3_purp.c (renamed from crypto/x509v3/v3_purp.c)487
-rw-r--r--crypto/x509/v3_san.c (renamed from crypto/x509v3/v3_alt.c)266
-rw-r--r--crypto/x509/v3_skid.c (renamed from crypto/x509v3/v3_skey.c)77
-rw-r--r--crypto/x509/v3_sxnet.c (renamed from crypto/x509v3/v3_sxnet.c)52
-rw-r--r--crypto/x509/v3_tlsf.c (renamed from crypto/x509v3/v3_tlsf.c)23
-rw-r--r--crypto/x509/v3_utf8.c68
-rw-r--r--crypto/x509/v3_utl.c (renamed from crypto/x509v3/v3_utl.c)239
-rw-r--r--crypto/x509/v3err.c (renamed from crypto/x509v3/v3err.c)136
-rw-r--r--crypto/x509/x509_att.c135
-rw-r--r--crypto/x509/x509_cmp.c251
-rw-r--r--crypto/x509/x509_d2.c96
-rw-r--r--crypto/x509/x509_def.c2
-rw-r--r--crypto/x509/x509_err.c120
-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.c73
-rw-r--r--crypto/x509/x509_set.c99
-rw-r--r--crypto/x509/x509_trust.c (renamed from crypto/x509/x509_trs.c)30
-rw-r--r--crypto/x509/x509_txt.c71
-rw-r--r--crypto/x509/x509_v3.c18
-rw-r--r--crypto/x509/x509_vfy.c1645
-rw-r--r--crypto/x509/x509_vpm.c152
-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.c432
-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.c66
-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/standard_exts.h78
-rw-r--r--crypto/x86_64cpuid.pl25
-rw-r--r--crypto/x86cpuid.pl6
1178 files changed, 131812 insertions, 43641 deletions
diff --git a/crypto/LPdir_nyi.c b/crypto/LPdir_nyi.c
new file mode 100644
index 000000000000..a1540785f87d
--- /dev/null
+++ b/crypto/LPdir_nyi.c
@@ -0,0 +1,56 @@
+/*
+ * 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, Richard Levitte <richard@levitte.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+#ifndef LPDIR_H
+# include "LPdir.h"
+#endif
+
+struct LP_dir_context_st {
+ void *dummy;
+};
+const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
+{
+ errno = EINVAL;
+ return 0;
+}
+
+int LP_find_file_end(LP_DIR_CTX **ctx)
+{
+ errno = EINVAL;
+ return 0;
+}
diff --git a/crypto/LPdir_unix.c b/crypto/LPdir_unix.c
index bbbec0aee138..b6dda7bce2ec 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-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
@@ -137,11 +137,12 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
if ((*ctx)->expect_file_generations) {
char *p = (*ctx)->entry_name + strlen((*ctx)->entry_name);
- while(p > (*ctx)->entry_name && isdigit(p[-1]))
+ while (p > (*ctx)->entry_name && isdigit((unsigned char)p[-1]))
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/LPdir_vms.c b/crypto/LPdir_vms.c
new file mode 100644
index 000000000000..51043263ae67
--- /dev/null
+++ b/crypto/LPdir_vms.c
@@ -0,0 +1,207 @@
+/*
+ * 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, Richard Levitte <richard@levitte.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <descrip.h>
+#include <namdef.h>
+#include <rmsdef.h>
+#include <libfildef.h>
+#include <lib$routines.h>
+#include <strdef.h>
+#include <str$routines.h>
+#include <stsdef.h>
+#ifndef LPDIR_H
+# include "LPdir.h"
+#endif
+#include "vms_rms.h"
+
+/* Some compiler options hide EVMSERR. */
+#ifndef EVMSERR
+# define EVMSERR 65535 /* error for non-translatable VMS errors */
+#endif
+
+struct LP_dir_context_st {
+ unsigned long VMS_context;
+ char filespec[NAMX_MAXRSS + 1];
+ char result[NAMX_MAXRSS + 1];
+ struct dsc$descriptor_d filespec_dsc;
+ struct dsc$descriptor_d result_dsc;
+};
+
+const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
+{
+ int status;
+ char *p, *r;
+ size_t l;
+ unsigned long flags = 0;
+
+/* Arrange 32-bit pointer to (copied) string storage, if needed. */
+#if __INITIAL_POINTER_SIZE == 64
+# pragma pointer_size save
+# pragma pointer_size 32
+ char *ctx_filespec_32p;
+# pragma pointer_size restore
+ char ctx_filespec_32[NAMX_MAXRSS + 1];
+#endif /* __INITIAL_POINTER_SIZE == 64 */
+
+#ifdef NAML$C_MAXRSS
+ flags |= LIB$M_FIL_LONG_NAMES;
+#endif
+
+ if (ctx == NULL || directory == NULL) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ errno = 0;
+ if (*ctx == NULL) {
+ size_t filespeclen = strlen(directory);
+ char *filespec = NULL;
+
+ if (filespeclen == 0) {
+ errno = ENOENT;
+ return 0;
+ }
+
+ /* MUST be a VMS directory specification! Let's estimate if it is. */
+ if (directory[filespeclen - 1] != ']'
+ && directory[filespeclen - 1] != '>'
+ && directory[filespeclen - 1] != ':') {
+ errno = EINVAL;
+ return 0;
+ }
+
+ filespeclen += 4; /* "*.*;" */
+
+ if (filespeclen > NAMX_MAXRSS) {
+ errno = ENAMETOOLONG;
+ return 0;
+ }
+
+ *ctx = malloc(sizeof(**ctx));
+ if (*ctx == NULL) {
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(*ctx, 0, sizeof(**ctx));
+
+ strcpy((*ctx)->filespec, directory);
+ strcat((*ctx)->filespec, "*.*;");
+
+/* Arrange 32-bit pointer to (copied) string storage, if needed. */
+#if __INITIAL_POINTER_SIZE == 64
+# define CTX_FILESPEC ctx_filespec_32p
+ /* Copy the file name to storage with a 32-bit pointer. */
+ ctx_filespec_32p = ctx_filespec_32;
+ strcpy(ctx_filespec_32p, (*ctx)->filespec);
+#else /* __INITIAL_POINTER_SIZE == 64 */
+# define CTX_FILESPEC (*ctx)->filespec
+#endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+
+ (*ctx)->filespec_dsc.dsc$w_length = filespeclen;
+ (*ctx)->filespec_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ (*ctx)->filespec_dsc.dsc$b_class = DSC$K_CLASS_S;
+ (*ctx)->filespec_dsc.dsc$a_pointer = CTX_FILESPEC;
+ }
+
+ (*ctx)->result_dsc.dsc$w_length = 0;
+ (*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ (*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D;
+ (*ctx)->result_dsc.dsc$a_pointer = 0;
+
+ status = lib$find_file(&(*ctx)->filespec_dsc, &(*ctx)->result_dsc,
+ &(*ctx)->VMS_context, 0, 0, 0, &flags);
+
+ if (status == RMS$_NMF) {
+ errno = 0;
+ vaxc$errno = status;
+ return NULL;
+ }
+
+ if (!$VMS_STATUS_SUCCESS(status)) {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return NULL;
+ }
+
+ /*
+ * Quick, cheap and dirty way to discard any device and directory, since
+ * we only want file names
+ */
+ l = (*ctx)->result_dsc.dsc$w_length;
+ p = (*ctx)->result_dsc.dsc$a_pointer;
+ r = p;
+ for (; *p; p++) {
+ if (*p == '^' && p[1] != '\0') { /* Take care of ODS-5 escapes */
+ p++;
+ } else if (*p == ':' || *p == '>' || *p == ']') {
+ l -= p + 1 - r;
+ r = p + 1;
+ } else if (*p == ';') {
+ l = p - r;
+ break;
+ }
+ }
+
+ strncpy((*ctx)->result, r, l);
+ (*ctx)->result[l] = '\0';
+ str$free1_dx(&(*ctx)->result_dsc);
+
+ return (*ctx)->result;
+}
+
+int LP_find_file_end(LP_DIR_CTX **ctx)
+{
+ if (ctx != NULL && *ctx != NULL) {
+ int status = lib$find_file_end(&(*ctx)->VMS_context);
+
+ free(*ctx);
+
+ if (!$VMS_STATUS_SUCCESS(status)) {
+ errno = EVMSERR;
+ vaxc$errno = status;
+ return 0;
+ }
+ return 1;
+ }
+ errno = EINVAL;
+ return 0;
+}
diff --git a/crypto/LPdir_win.c b/crypto/LPdir_win.c
new file mode 100644
index 000000000000..83cbe1fc0907
--- /dev/null
+++ b/crypto/LPdir_win.c
@@ -0,0 +1,214 @@
+/*
+ * 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, Richard Levitte <richard@levitte.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 <windows.h>
+#include <tchar.h>
+#include "internal/numbers.h"
+#ifndef LPDIR_H
+# include "LPdir.h"
+#endif
+
+/*
+ * We're most likely overcautious here, but let's reserve for broken WinCE
+ * headers and explicitly opt for UNICODE call. Keep in mind that our WinCE
+ * builds are compiled with -DUNICODE [as well as -D_UNICODE].
+ */
+#if defined(LP_SYS_WINCE) && !defined(FindFirstFile)
+# define FindFirstFile FindFirstFileW
+#endif
+#if defined(LP_SYS_WINCE) && !defined(FindNextFile)
+# define FindNextFile FindNextFileW
+#endif
+
+#ifndef NAME_MAX
+# define NAME_MAX 255
+#endif
+
+#ifdef CP_UTF8
+# define CP_DEFAULT CP_UTF8
+#else
+# define CP_DEFAULT CP_ACP
+#endif
+
+struct LP_dir_context_st {
+ WIN32_FIND_DATA ctx;
+ HANDLE handle;
+ char entry_name[NAME_MAX + 1];
+};
+
+const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
+{
+ if (ctx == NULL || directory == NULL) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ errno = 0;
+ if (*ctx == NULL) {
+ size_t dirlen = strlen(directory);
+
+ if (dirlen == 0 || dirlen > INT_MAX - 3) {
+ errno = ENOENT;
+ return 0;
+ }
+
+ *ctx = malloc(sizeof(**ctx));
+ if (*ctx == NULL) {
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(*ctx, 0, sizeof(**ctx));
+
+ if (sizeof(TCHAR) != sizeof(char)) {
+ TCHAR *wdir = NULL;
+ /* len_0 denotes string length *with* trailing 0 */
+ size_t index = 0, len_0 = dirlen + 1;
+#ifdef LP_MULTIBYTE_AVAILABLE
+ int sz = 0;
+ UINT cp;
+
+ do {
+# ifdef CP_UTF8
+ if ((sz = MultiByteToWideChar((cp = CP_UTF8), 0,
+ directory, len_0,
+ NULL, 0)) > 0 ||
+ GetLastError() != ERROR_NO_UNICODE_TRANSLATION)
+ break;
+# endif
+ sz = MultiByteToWideChar((cp = CP_ACP), 0,
+ directory, len_0,
+ NULL, 0);
+ } while (0);
+
+ if (sz > 0) {
+ /*
+ * allocate two additional characters in case we need to
+ * concatenate asterisk, |sz| covers trailing '\0'!
+ */
+ wdir = _alloca((sz + 2) * sizeof(TCHAR));
+ if (!MultiByteToWideChar(cp, 0, directory, len_0,
+ (WCHAR *)wdir, sz)) {
+ free(*ctx);
+ *ctx = NULL;
+ errno = EINVAL;
+ return 0;
+ }
+ } else
+#endif
+ {
+ sz = len_0;
+ /*
+ * allocate two additional characters in case we need to
+ * concatenate asterisk, |sz| covers trailing '\0'!
+ */
+ wdir = _alloca((sz + 2) * sizeof(TCHAR));
+ for (index = 0; index < len_0; index++)
+ wdir[index] = (TCHAR)directory[index];
+ }
+
+ sz--; /* wdir[sz] is trailing '\0' now */
+ if (wdir[sz - 1] != TEXT('*')) {
+ if (wdir[sz - 1] != TEXT('/') && wdir[sz - 1] != TEXT('\\'))
+ _tcscpy(wdir + sz, TEXT("/*"));
+ else
+ _tcscpy(wdir + sz, TEXT("*"));
+ }
+
+ (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);
+ } else {
+ if (directory[dirlen - 1] != '*') {
+ char *buf = _alloca(dirlen + 3);
+
+ strcpy(buf, directory);
+ if (buf[dirlen - 1] != '/' && buf[dirlen - 1] != '\\')
+ strcpy(buf + dirlen, "/*");
+ else
+ strcpy(buf + dirlen, "*");
+
+ directory = buf;
+ }
+
+ (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);
+ }
+
+ if ((*ctx)->handle == INVALID_HANDLE_VALUE) {
+ free(*ctx);
+ *ctx = NULL;
+ errno = EINVAL;
+ return 0;
+ }
+ } else {
+ if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) {
+ return 0;
+ }
+ }
+ if (sizeof(TCHAR) != sizeof(char)) {
+ TCHAR *wdir = (*ctx)->ctx.cFileName;
+ size_t index, len_0 = 0;
+
+ while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1))
+ len_0++;
+ len_0++;
+
+#ifdef LP_MULTIBYTE_AVAILABLE
+ if (!WideCharToMultiByte(CP_DEFAULT, 0, (WCHAR *)wdir, len_0,
+ (*ctx)->entry_name,
+ sizeof((*ctx)->entry_name), NULL, 0))
+#endif
+ for (index = 0; index < len_0; index++)
+ (*ctx)->entry_name[index] = (char)wdir[index];
+ } else
+ strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
+ sizeof((*ctx)->entry_name) - 1);
+
+ (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
+
+ return (*ctx)->entry_name;
+}
+
+int LP_find_file_end(LP_DIR_CTX **ctx)
+{
+ if (ctx != NULL && *ctx != NULL) {
+ FindClose((*ctx)->handle);
+ free(*ctx);
+ *ctx = NULL;
+ return 1;
+ }
+ errno = EINVAL;
+ return 0;
+}
diff --git a/crypto/LPdir_win32.c b/crypto/LPdir_win32.c
new file mode 100644
index 000000000000..b29e096ff30f
--- /dev/null
+++ b/crypto/LPdir_win32.c
@@ -0,0 +1,41 @@
+/*
+ * 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, Richard Levitte <richard@levitte.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+#define LP_SYS_WIN32
+#define LP_MULTIBYTE_AVAILABLE
+#include "LPdir_win.c"
diff --git a/crypto/LPdir_wince.c b/crypto/LPdir_wince.c
new file mode 100644
index 000000000000..ebf89628272a
--- /dev/null
+++ b/crypto/LPdir_wince.c
@@ -0,0 +1,44 @@
+/*
+ * 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, Richard Levitte <richard@levitte.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+#define LP_SYS_WINCE
+/*
+ * We might want to define LP_MULTIBYTE_AVAILABLE here. It's currently under
+ * investigation what the exact conditions would be
+ */
+#include "LPdir_win.c"
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..f7f78d04b0e1 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.
+# Copyright 2014-2024 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with 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";
@@ -95,11 +99,12 @@ rcon:
.long 0x1b000000, 0x1b000000, 0x1b000000, 0x1b000000 ?rev
.long 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c ?rev
.long 0,0,0,0 ?asis
+.long 0x0f102132, 0x43546576, 0x8798a9ba, 0xcbdcedfe
Lconsts:
mflr r0
bcl 20,31,\$+4
mflr $ptr #vvvvv "distance between . and rcon
- addi $ptr,$ptr,-0x48
+ addi $ptr,$ptr,-0x58
mtlr r0
blr
.long 0
@@ -2401,7 +2406,7 @@ ___
my $key_=$key2;
my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,3,26..31));
$x00=0 if ($flavour =~ /osx/);
-my ($in0, $in1, $in2, $in3, $in4, $in5 )=map("v$_",(0..5));
+my ($in0, $in1, $in2, $in3, $in4, $in5)=map("v$_",(0..5));
my ($out0, $out1, $out2, $out3, $out4, $out5)=map("v$_",(7,12..16));
my ($twk0, $twk1, $twk2, $twk3, $twk4, $twk5)=map("v$_",(17..22));
my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys
@@ -2456,6 +2461,18 @@ _aesp8_xts_encrypt6x:
li $x70,0x70
mtspr 256,r0
+ # Reverse eighty7 to 0x010101..87
+ xxlor 2, 32+$eighty7, 32+$eighty7
+ vsldoi $eighty7,$tmp,$eighty7,1 # 0x010101..87
+ xxlor 1, 32+$eighty7, 32+$eighty7
+
+ # Load XOR contents. 0xf102132435465768798a9bacbdcedfe
+ mr $x70, r6
+ bl Lconsts
+ lxvw4x 0, $x40, r6 # load XOR contents
+ mr r6, $x70
+ li $x70,0x70
+
subi $rounds,$rounds,3 # -4 in total
lvx $rndkey0,$x00,$key1 # load key schedule
@@ -2498,69 +2515,77 @@ Load_xts_enc_key:
?vperm v31,v31,$twk5,$keyperm
lvx v25,$x10,$key_ # pre-load round[2]
+ # Switch to use the following codes with 0x010101..87 to generate tweak.
+ # eighty7 = 0x010101..87
+ # vsrab tmp, tweak, seven # next tweak value, right shift 7 bits
+ # vand tmp, tmp, eighty7 # last byte with carry
+ # vaddubm tweak, tweak, tweak # left shift 1 bit (x2)
+ # xxlor vsx, 0, 0
+ # vpermxor tweak, tweak, tmp, vsx
+
vperm $in0,$inout,$inptail,$inpperm
subi $inp,$inp,31 # undo "caller"
vxor $twk0,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $out0,$in0,$twk0
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in1, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in1
lvx_u $in1,$x10,$inp
vxor $twk1,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in1,$in1,$in1,$leperm
vand $tmp,$tmp,$eighty7
vxor $out1,$in1,$twk1
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in2, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in2
lvx_u $in2,$x20,$inp
andi. $taillen,$len,15
vxor $twk2,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in2,$in2,$in2,$leperm
vand $tmp,$tmp,$eighty7
vxor $out2,$in2,$twk2
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in3, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in3
lvx_u $in3,$x30,$inp
sub $len,$len,$taillen
vxor $twk3,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in3,$in3,$in3,$leperm
vand $tmp,$tmp,$eighty7
vxor $out3,$in3,$twk3
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in4, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in4
lvx_u $in4,$x40,$inp
subi $len,$len,0x60
vxor $twk4,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in4,$in4,$in4,$leperm
vand $tmp,$tmp,$eighty7
vxor $out4,$in4,$twk4
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in5, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in5
lvx_u $in5,$x50,$inp
addi $inp,$inp,0x60
vxor $twk5,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in5,$in5,$in5,$leperm
vand $tmp,$tmp,$eighty7
vxor $out5,$in5,$twk5
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in0, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in0
vxor v31,v31,$rndkey0
mtctr $rounds
@@ -2586,6 +2611,8 @@ Loop_xts_enc6x:
lvx v25,$x10,$key_ # round[4]
bdnz Loop_xts_enc6x
+ xxlor 32+$eighty7, 1, 1 # 0x010101..87
+
subic $len,$len,96 # $len-=96
vxor $in0,$twk0,v31 # xor with last round key
vcipher $out0,$out0,v24
@@ -2595,7 +2622,6 @@ Loop_xts_enc6x:
vaddubm $tweak,$tweak,$tweak
vcipher $out2,$out2,v24
vcipher $out3,$out3,v24
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out4,$out4,v24
vcipher $out5,$out5,v24
@@ -2603,7 +2629,8 @@ Loop_xts_enc6x:
vand $tmp,$tmp,$eighty7
vcipher $out0,$out0,v25
vcipher $out1,$out1,v25
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in1, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in1
vcipher $out2,$out2,v25
vcipher $out3,$out3,v25
vxor $in1,$twk1,v31
@@ -2614,13 +2641,13 @@ Loop_xts_enc6x:
and r0,r0,$len
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out0,$out0,v26
vcipher $out1,$out1,v26
vand $tmp,$tmp,$eighty7
vcipher $out2,$out2,v26
vcipher $out3,$out3,v26
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in2, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in2
vcipher $out4,$out4,v26
vcipher $out5,$out5,v26
@@ -2634,7 +2661,6 @@ Loop_xts_enc6x:
vaddubm $tweak,$tweak,$tweak
vcipher $out0,$out0,v27
vcipher $out1,$out1,v27
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out2,$out2,v27
vcipher $out3,$out3,v27
vand $tmp,$tmp,$eighty7
@@ -2642,7 +2668,8 @@ Loop_xts_enc6x:
vcipher $out5,$out5,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in3, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in3
vcipher $out0,$out0,v28
vcipher $out1,$out1,v28
vxor $in3,$twk3,v31
@@ -2651,7 +2678,6 @@ Loop_xts_enc6x:
vcipher $out2,$out2,v28
vcipher $out3,$out3,v28
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out4,$out4,v28
vcipher $out5,$out5,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
@@ -2659,7 +2685,8 @@ Loop_xts_enc6x:
vcipher $out0,$out0,v29
vcipher $out1,$out1,v29
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in4, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in4
vcipher $out2,$out2,v29
vcipher $out3,$out3,v29
vxor $in4,$twk4,v31
@@ -2669,14 +2696,14 @@ Loop_xts_enc6x:
vcipher $out5,$out5,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vcipher $out0,$out0,v30
vcipher $out1,$out1,v30
vand $tmp,$tmp,$eighty7
vcipher $out2,$out2,v30
vcipher $out3,$out3,v30
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in5, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in5
vcipher $out4,$out4,v30
vcipher $out5,$out5,v30
vxor $in5,$twk5,v31
@@ -2686,7 +2713,6 @@ Loop_xts_enc6x:
vcipherlast $out0,$out0,$in0
lvx_u $in0,$x00,$inp # load next input block
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vcipherlast $out1,$out1,$in1
lvx_u $in1,$x10,$inp
vcipherlast $out2,$out2,$in2
@@ -2699,7 +2725,10 @@ Loop_xts_enc6x:
vcipherlast $out4,$out4,$in4
le?vperm $in2,$in2,$in2,$leperm
lvx_u $in4,$x40,$inp
- vxor $tweak,$tweak,$tmp
+ xxlor 10, 32+$in0, 32+$in0
+ xxlor 32+$in0, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in0
+ xxlor 32+$in0, 10, 10
vcipherlast $tmp,$out5,$in5 # last block might be needed
# in stealing mode
le?vperm $in3,$in3,$in3,$leperm
@@ -2732,6 +2761,8 @@ Loop_xts_enc6x:
mtctr $rounds
beq Loop_xts_enc6x # did $len-=96 borrow?
+ xxlor 32+$eighty7, 2, 2 # 0x870101..01
+
addic. $len,$len,0x60
beq Lxts_enc6x_zero
cmpwi $len,0x20
@@ -3108,6 +3139,18 @@ _aesp8_xts_decrypt6x:
li $x70,0x70
mtspr 256,r0
+ # Reverse eighty7 to 0x010101..87
+ xxlor 2, 32+$eighty7, 32+$eighty7
+ vsldoi $eighty7,$tmp,$eighty7,1 # 0x010101..87
+ xxlor 1, 32+$eighty7, 32+$eighty7
+
+ # Load XOR contents. 0xf102132435465768798a9bacbdcedfe
+ mr $x70, r6
+ bl Lconsts
+ lxvw4x 0, $x40, r6 # load XOR contents
+ mr r6, $x70
+ li $x70,0x70
+
subi $rounds,$rounds,3 # -4 in total
lvx $rndkey0,$x00,$key1 # load key schedule
@@ -3155,64 +3198,64 @@ Load_xts_dec_key:
vxor $twk0,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $out0,$in0,$twk0
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in1, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in1
lvx_u $in1,$x10,$inp
vxor $twk1,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in1,$in1,$in1,$leperm
vand $tmp,$tmp,$eighty7
vxor $out1,$in1,$twk1
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in2, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in2
lvx_u $in2,$x20,$inp
andi. $taillen,$len,15
vxor $twk2,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in2,$in2,$in2,$leperm
vand $tmp,$tmp,$eighty7
vxor $out2,$in2,$twk2
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in3, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in3
lvx_u $in3,$x30,$inp
sub $len,$len,$taillen
vxor $twk3,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in3,$in3,$in3,$leperm
vand $tmp,$tmp,$eighty7
vxor $out3,$in3,$twk3
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in4, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in4
lvx_u $in4,$x40,$inp
subi $len,$len,0x60
vxor $twk4,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in4,$in4,$in4,$leperm
vand $tmp,$tmp,$eighty7
vxor $out4,$in4,$twk4
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in5, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in5
lvx_u $in5,$x50,$inp
addi $inp,$inp,0x60
vxor $twk5,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
le?vperm $in5,$in5,$in5,$leperm
vand $tmp,$tmp,$eighty7
vxor $out5,$in5,$twk5
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in0, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in0
vxor v31,v31,$rndkey0
mtctr $rounds
@@ -3238,6 +3281,8 @@ Loop_xts_dec6x:
lvx v25,$x10,$key_ # round[4]
bdnz Loop_xts_dec6x
+ xxlor 32+$eighty7, 1, 1
+
subic $len,$len,96 # $len-=96
vxor $in0,$twk0,v31 # xor with last round key
vncipher $out0,$out0,v24
@@ -3247,7 +3292,6 @@ Loop_xts_dec6x:
vaddubm $tweak,$tweak,$tweak
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out4,$out4,v24
vncipher $out5,$out5,v24
@@ -3255,7 +3299,8 @@ Loop_xts_dec6x:
vand $tmp,$tmp,$eighty7
vncipher $out0,$out0,v25
vncipher $out1,$out1,v25
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in1, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in1
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vxor $in1,$twk1,v31
@@ -3266,13 +3311,13 @@ Loop_xts_dec6x:
and r0,r0,$len
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out0,$out0,v26
vncipher $out1,$out1,v26
vand $tmp,$tmp,$eighty7
vncipher $out2,$out2,v26
vncipher $out3,$out3,v26
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in2, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in2
vncipher $out4,$out4,v26
vncipher $out5,$out5,v26
@@ -3286,7 +3331,6 @@ Loop_xts_dec6x:
vaddubm $tweak,$tweak,$tweak
vncipher $out0,$out0,v27
vncipher $out1,$out1,v27
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out2,$out2,v27
vncipher $out3,$out3,v27
vand $tmp,$tmp,$eighty7
@@ -3294,7 +3338,8 @@ Loop_xts_dec6x:
vncipher $out5,$out5,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in3, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in3
vncipher $out0,$out0,v28
vncipher $out1,$out1,v28
vxor $in3,$twk3,v31
@@ -3303,7 +3348,6 @@ Loop_xts_dec6x:
vncipher $out2,$out2,v28
vncipher $out3,$out3,v28
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out4,$out4,v28
vncipher $out5,$out5,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
@@ -3311,7 +3355,8 @@ Loop_xts_dec6x:
vncipher $out0,$out0,v29
vncipher $out1,$out1,v29
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in4, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in4
vncipher $out2,$out2,v29
vncipher $out3,$out3,v29
vxor $in4,$twk4,v31
@@ -3321,14 +3366,14 @@ Loop_xts_dec6x:
vncipher $out5,$out5,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vncipher $out0,$out0,v30
vncipher $out1,$out1,v30
vand $tmp,$tmp,$eighty7
vncipher $out2,$out2,v30
vncipher $out3,$out3,v30
- vxor $tweak,$tweak,$tmp
+ xxlor 32+$in5, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in5
vncipher $out4,$out4,v30
vncipher $out5,$out5,v30
vxor $in5,$twk5,v31
@@ -3338,7 +3383,6 @@ Loop_xts_dec6x:
vncipherlast $out0,$out0,$in0
lvx_u $in0,$x00,$inp # load next input block
vaddubm $tweak,$tweak,$tweak
- vsldoi $tmp,$tmp,$tmp,15
vncipherlast $out1,$out1,$in1
lvx_u $in1,$x10,$inp
vncipherlast $out2,$out2,$in2
@@ -3351,7 +3395,10 @@ Loop_xts_dec6x:
vncipherlast $out4,$out4,$in4
le?vperm $in2,$in2,$in2,$leperm
lvx_u $in4,$x40,$inp
- vxor $tweak,$tweak,$tmp
+ xxlor 10, 32+$in0, 32+$in0
+ xxlor 32+$in0, 0, 0
+ vpermxor $tweak, $tweak, $tmp, $in0
+ xxlor 32+$in0, 10, 10
vncipherlast $out5,$out5,$in5
le?vperm $in3,$in3,$in3,$leperm
lvx_u $in5,$x50,$inp
@@ -3382,6 +3429,8 @@ Loop_xts_dec6x:
mtctr $rounds
beq Loop_xts_dec6x # did $len-=96 borrow?
+ xxlor 32+$eighty7, 2, 2
+
addic. $len,$len,0x60
beq Lxts_dec6x_zero
cmpwi $len,0x20
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..d0e0be6187bd 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.
+# 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
@@ -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,1434 @@ $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.32 {$dat},[$key2],#16
+ vld1.8 {$iv0},[$ivp]
+ sub $rounds,$rounds,#2
+ vld1.32 {$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.32 {$dat},[$key1],#16
+ sub $rounds,$rounds,#2
+ vld1.32 {$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.32 {$dat},[$key2],#16
+ vld1.8 {$iv0},[$ivp]
+ sub $rounds,$rounds,#2
+ vld1.32 {$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.32 {$dat},[$key2],#16
+ vld1.8 {$iv0},[$ivp]
+ sub $rounds,$rounds,#2
+ vld1.32 {$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
+ tst $tailcnt,#0xf
+ 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.eq .Lxts_dec_abort
+ vld1.8 {$dat0},[$inp],#16
+ 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.8 {$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.32 {$dat},[$key_],#16
+ sub $rounds,$rounds,#2
+ vld1.32 {$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
___
@@ -1009,6 +3661,9 @@ if ($flavour =~ /64/) { ######## 64-bit code
s/\.[ui]?64//o and s/\.16b/\.2d/go;
s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o;
+ # Switch preprocessor checks to aarch64 versions.
+ s/__ARME([BL])__/__AARCH64E$1__/go;
+
print $_,"\n";
}
} else { ######## 32-bit code
@@ -1025,7 +3680,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 +3721,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..6cbd00e2c672 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-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
@@ -14,7 +14,7 @@
# details see http://www.openssl.org/~appro/cryptogams/.
#
# Specific modes and adaptation for Linux kernel by Ard Biesheuvel
-# of Linaro. Permission to use under GPL terms is granted.
+# of Linaro.
# ====================================================================
# Bit-sliced AES for ARM NEON
@@ -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
@@ -1444,7 +1447,7 @@ bsaes_ctr32_encrypt_blocks:
.align 2
0: add r12, $key, #248
vld1.8 {@XMM[0]}, [$ctr] @ load counter
- adrl $ctr, .LREVM0SR @ borrow $ctr
+ add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr
vldmia r12, {@XMM[4]} @ load round0 key
sub sp, #0x10 @ place for adjusted round0 key
#endif
@@ -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..d6ad4ea3d068 100644
--- a/crypto/aes/build.info
+++ b/crypto/aes/build.info
@@ -1,64 +1,132 @@
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
+
+ IF[{- $target{sys_id} ne "MACOSX" -}]
+ $AESASM_ppc32=aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s aesp8-ppc.s
+ ELSE
+ $AESASM_ppc32=aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s
+ ENDIF
+ $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/alphacpuid.pl b/crypto/alphacpuid.pl
new file mode 100644
index 000000000000..b96975038060
--- /dev/null
+++ b/crypto/alphacpuid.pl
@@ -0,0 +1,256 @@
+#! /usr/bin/env perl
+# Copyright 2010-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
+
+
+$output = pop and open STDOUT,">$output";
+
+print <<'___';
+.text
+
+.set noat
+
+.globl OPENSSL_cpuid_setup
+.ent OPENSSL_cpuid_setup
+OPENSSL_cpuid_setup:
+ .frame $30,0,$26
+ .prologue 0
+ ret ($26)
+.end OPENSSL_cpuid_setup
+
+.globl OPENSSL_wipe_cpu
+.ent OPENSSL_wipe_cpu
+OPENSSL_wipe_cpu:
+ .frame $30,0,$26
+ .prologue 0
+ clr $1
+ clr $2
+ clr $3
+ clr $4
+ clr $5
+ clr $6
+ clr $7
+ clr $8
+ clr $16
+ clr $17
+ clr $18
+ clr $19
+ clr $20
+ clr $21
+ clr $22
+ clr $23
+ clr $24
+ clr $25
+ clr $27
+ clr $at
+ clr $29
+ fclr $f0
+ fclr $f1
+ fclr $f10
+ fclr $f11
+ fclr $f12
+ fclr $f13
+ fclr $f14
+ fclr $f15
+ fclr $f16
+ fclr $f17
+ fclr $f18
+ fclr $f19
+ fclr $f20
+ fclr $f21
+ fclr $f22
+ fclr $f23
+ fclr $f24
+ fclr $f25
+ fclr $f26
+ fclr $f27
+ fclr $f28
+ fclr $f29
+ fclr $f30
+ mov $sp,$0
+ ret ($26)
+.end OPENSSL_wipe_cpu
+
+.globl OPENSSL_atomic_add
+.ent OPENSSL_atomic_add
+OPENSSL_atomic_add:
+ .frame $30,0,$26
+ .prologue 0
+1: ldl_l $0,0($16)
+ addl $0,$17,$1
+ stl_c $1,0($16)
+ beq $1,1b
+ addl $0,$17,$0
+ ret ($26)
+.end OPENSSL_atomic_add
+
+.globl OPENSSL_rdtsc
+.ent OPENSSL_rdtsc
+OPENSSL_rdtsc:
+ .frame $30,0,$26
+ .prologue 0
+ rpcc $0
+ ret ($26)
+.end OPENSSL_rdtsc
+
+.globl OPENSSL_cleanse
+.ent OPENSSL_cleanse
+OPENSSL_cleanse:
+ .frame $30,0,$26
+ .prologue 0
+ beq $17,.Ldone
+ and $16,7,$0
+ bic $17,7,$at
+ beq $at,.Little
+ beq $0,.Laligned
+
+.Little:
+ subq $0,8,$0
+ ldq_u $1,0($16)
+ mov $16,$2
+.Lalign:
+ mskbl $1,$16,$1
+ lda $16,1($16)
+ subq $17,1,$17
+ addq $0,1,$0
+ beq $17,.Lout
+ bne $0,.Lalign
+.Lout: stq_u $1,0($2)
+ beq $17,.Ldone
+ bic $17,7,$at
+ beq $at,.Little
+
+.Laligned:
+ stq $31,0($16)
+ subq $17,8,$17
+ lda $16,8($16)
+ bic $17,7,$at
+ bne $at,.Laligned
+ bne $17,.Little
+.Ldone: ret ($26)
+.end OPENSSL_cleanse
+
+.globl CRYPTO_memcmp
+.ent CRYPTO_memcmp
+CRYPTO_memcmp:
+ .frame $30,0,$26
+ .prologue 0
+ xor $0,$0,$0
+ beq $18,.Lno_data
+
+ xor $1,$1,$1
+ nop
+.Loop_cmp:
+ ldq_u $2,0($16)
+ subq $18,1,$18
+ ldq_u $3,0($17)
+ extbl $2,$16,$2
+ lda $16,1($16)
+ extbl $3,$17,$3
+ lda $17,1($17)
+ xor $3,$2,$2
+ or $2,$0,$0
+ bne $18,.Loop_cmp
+
+ subq $31,$0,$0
+ srl $0,63,$0
+.Lno_data:
+ ret ($26)
+.end CRYPTO_memcmp
+___
+{
+my ($out,$cnt,$max)=("\$16","\$17","\$18");
+my ($tick,$lasttick)=("\$19","\$20");
+my ($diff,$lastdiff)=("\$21","\$22");
+my ($v0,$ra,$sp,$zero)=("\$0","\$26","\$30","\$31");
+
+print <<___;
+.globl OPENSSL_instrument_bus
+.ent OPENSSL_instrument_bus
+OPENSSL_instrument_bus:
+ .frame $sp,0,$ra
+ .prologue 0
+ mov $cnt,$v0
+
+ rpcc $lasttick
+ mov 0,$diff
+
+ ecb ($out)
+ ldl_l $tick,0($out)
+ addl $diff,$tick,$tick
+ mov $tick,$diff
+ stl_c $tick,0($out)
+ stl $diff,0($out)
+
+.Loop: rpcc $tick
+ subq $tick,$lasttick,$diff
+ mov $tick,$lasttick
+
+ ecb ($out)
+ ldl_l $tick,0($out)
+ addl $diff,$tick,$tick
+ mov $tick,$diff
+ stl_c $tick,0($out)
+ stl $diff,0($out)
+
+ subl $cnt,1,$cnt
+ lda $out,4($out)
+ bne $cnt,.Loop
+
+ ret ($ra)
+.end OPENSSL_instrument_bus
+
+.globl OPENSSL_instrument_bus2
+.ent OPENSSL_instrument_bus2
+OPENSSL_instrument_bus2:
+ .frame $sp,0,$ra
+ .prologue 0
+ mov $cnt,$v0
+
+ rpcc $lasttick
+ mov 0,$diff
+
+ ecb ($out)
+ ldl_l $tick,0($out)
+ addl $diff,$tick,$tick
+ mov $tick,$diff
+ stl_c $tick,0($out)
+ stl $diff,0($out)
+
+ rpcc $tick
+ subq $tick,$lasttick,$diff
+ mov $tick,$lasttick
+ mov $diff,$lastdiff
+.Loop2:
+ ecb ($out)
+ ldl_l $tick,0($out)
+ addl $diff,$tick,$tick
+ mov $tick,$diff
+ stl_c $tick,0($out)
+ stl $diff,0($out)
+
+ subl $max,1,$max
+ beq $max,.Ldone2
+
+ rpcc $tick
+ subq $tick,$lasttick,$diff
+ mov $tick,$lasttick
+ subq $lastdiff,$diff,$tick
+ mov $diff,$lastdiff
+ cmovne $tick,1,$tick
+ subl $cnt,$tick,$cnt
+ s4addq $tick,$out,$out
+ bne $cnt,.Loop2
+
+.Ldone2:
+ subl $v0,$cnt,$v0
+ ret ($ra)
+.end OPENSSL_instrument_bus2
+___
+}
+
+close STDOUT or die "error closing STDOUT: $!";
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..ec4a087fede2 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-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
@@ -21,11 +21,6 @@
# elif defined(__GNUC__)
# if defined(__aarch64__)
# define __ARM_ARCH__ 8
-# if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
-# define __ARMEB__
-# else
-# define __ARMEL__
-# endif
/*
* Why doesn't gcc define __ARM_ARCH__? Instead it defines
* bunch of below macros. See all_architectures[] table in
@@ -71,6 +66,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 +77,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..549c0e885549 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-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
@@ -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;
@@ -36,25 +36,30 @@ int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
if (a->data[len - 1])
break;
}
- j = a->data[len - 1];
- if (j & 0x01)
+
+ if (len == 0) {
bits = 0;
- else if (j & 0x02)
- bits = 1;
- else if (j & 0x04)
- bits = 2;
- else if (j & 0x08)
- bits = 3;
- else if (j & 0x10)
- bits = 4;
- else if (j & 0x20)
- bits = 5;
- else if (j & 0x40)
- bits = 6;
- else if (j & 0x80)
- bits = 7;
- else
- bits = 0; /* should not happen */
+ } else {
+ j = a->data[len - 1];
+ if (j & 0x01)
+ bits = 0;
+ else if (j & 0x02)
+ bits = 1;
+ else if (j & 0x04)
+ bits = 2;
+ else if (j & 0x08)
+ bits = 3;
+ else if (j & 0x10)
+ bits = 4;
+ else if (j & 0x20)
+ bits = 5;
+ else if (j & 0x40)
+ bits = 6;
+ else if (j & 0x80)
+ bits = 7;
+ else
+ bits = 0; /* should not happen */
+ }
}
} else
bits = 0;
@@ -76,8 +81,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 +139,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;
@@ -148,6 +153,9 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
int w, v, iv;
unsigned char *c;
+ if (n < 0)
+ return 0;
+
w = n / 8;
v = 1 << (7 - (n & 0x07));
iv = ~v;
@@ -164,7 +172,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)
@@ -182,6 +190,9 @@ int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
{
int w, v;
+ if (n < 0)
+ return 0;
+
w = n / 8;
v = 1 << (7 - (n & 0x07));
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c
index a452b3deba08..bd549215b400 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,45 +123,51 @@ 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;
+ if ((size_t)i < want)
+ continue;
+
}
}
/* else data already loaded */
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 +175,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 +196,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 +209,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 +231,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 +243,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..bca1458ad6a1 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
}
@@ -141,15 +139,13 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
if (*out) {
free_out = 0;
dest = *out;
- OPENSSL_free(dest->data);
- dest->data = NULL;
- dest->length = 0;
+ ASN1_STRING_set0(dest, NULL, 0);
dest->type = str_type;
} else {
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 +153,11 @@ 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);
+ if (free_out) {
+ ASN1_STRING_free(dest);
+ *out = NULL;
+ }
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
return str_type;
@@ -187,9 +187,11 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
break;
}
if ((p = OPENSSL_malloc(outlen + 1)) == NULL) {
- if (free_out)
+ if (free_out) {
ASN1_STRING_free(dest);
- ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
+ *out = NULL;
+ }
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
dest->length = outlen;
@@ -247,6 +249,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 +261,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 +292,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..a6049f7dd2ed 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.
+ * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 <string.h>
#include "internal/cryptlib.h"
+#include "internal/sizes.h"
#include "crypto/asn1.h"
#include <openssl/crypto.h>
#include <openssl/x509.h>
@@ -32,7 +33,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 +153,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 +284,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;
@@ -345,8 +346,10 @@ static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
const char *tagname;
+
tagname = ASN1_tag2str(type);
- outlen += strlen(tagname);
+ /* We can directly cast here as tagname will never be too large. */
+ outlen += (int)strlen(tagname);
if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
return -1;
outlen++;
@@ -372,7 +375,7 @@ static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
if (type == -1) {
len = do_dump(lflags, io_ch, arg, str);
- if (len < 0)
+ if (len < 0 || len > INT_MAX - outlen)
return -1;
outlen += len;
return outlen;
@@ -391,7 +394,7 @@ static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
}
len = do_buf(str->data, str->length, type, flags, &quotes, io_ch, NULL);
- if (len < 0)
+ if (len < 0 || len > INT_MAX - 2 - outlen)
return -1;
outlen += len;
if (quotes)
diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c
index f19a9de647b1..20cfabc8a7a4 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,10 +39,10 @@ unsigned long ASN1_STRING_get_default_mask(void)
* This function sets the default to various "flavours" of configuration.
* based on an ASCII string. Currently this is:
* MASK:XXXX : a numerical mask value.
- * nobmp : Don't use BMPStrings (just Printable, T61).
- * pkix : PKIX recommendation in RFC2459.
- * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
- * default: the default value, Printable, T61, BMP.
+ * default : use Printable, IA5, T61, BMP, and UTF8 string types
+ * nombstr : any string type except variable-sized BMPStrings or UTF8Strings
+ * pkix : PKIX recommendation in RFC2459
+ * utf8only : this is the default, use UTF8Strings
*/
int ASN1_STRING_set_default_mask_asc(const char *p)
@@ -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,11 @@ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
int idx;
ASN1_STRING_TABLE fnd;
+#ifndef OPENSSL_NO_AUTOLOAD_CONFIG
+ /* "stable" can be impacted by config, so load the config file first */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#endif
+
fnd.nid = nid;
if (stable) {
idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
@@ -157,7 +162,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 +192,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..5ef6d0d1cd1c 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,22 +470,34 @@ 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;
+ int l;
struct tm stm;
- const char upper_z = 0x5A, period = 0x2E;
+ const char 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;
- if (v[l - 1] == upper_z)
- gmt = 1;
if (tm->type == V_ASN1_GENERALIZEDTIME) {
char *f = NULL;
@@ -492,25 +508,37 @@ int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
* 'fraction point' in a GeneralizedTime string.
*/
if (tm->length > 15 && v[14] == period) {
- f = &v[14];
- f_len = 1;
- while (14 + f_len < l && ascii_isdigit(f[f_len]))
+ /* exclude the . itself */
+ f = &v[15];
+ f_len = 0;
+ while (15 + f_len < l && ossl_ascii_isdigit(f[f_len]))
++f_len;
}
- 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;
+ if (f_len > 0) {
+ if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+ return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d.%.*sZ",
+ stm.tm_year + 1900, stm.tm_mon + 1,
+ stm.tm_mday, stm.tm_hour,
+ stm.tm_min, stm.tm_sec, f_len, f) > 0;
+ } else {
+ return BIO_printf(bp, "%s %2d %02d:%02d:%02d.%.*s %d GMT",
+ _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
+ stm.tm_min, stm.tm_sec, f_len, f,
+ stm.tm_year + 1900) > 0;
+ }
+ }
+ }
+ if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+ return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02dZ",
+ stm.tm_year + 1900, stm.tm_mon + 1,
+ stm.tm_mday, stm.tm_hour,
+ stm.tm_min, stm.tm_sec) > 0;
} else {
- return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
+ return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d GMT",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
- stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
- (gmt ? " GMT" : "")) > 0;
+ stm.tm_min, stm.tm_sec, stm.tm_year + 1900) > 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 +569,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..66809bd6d2ff 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,129 @@ 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);
+ ret = -1;
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);
+ ret = -1;
goto err;
}
inll = inl;
@@ -167,12 +216,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..152dc870a558 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
}
@@ -502,7 +498,8 @@ static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
static int asn1_str2tag(const char *tagstr, int len)
{
unsigned int i;
- static const struct tag_name_st *tntmp, tnst[] = {
+ const struct tag_name_st *tntmp;
+ static const struct tag_name_st tnst[] = {
ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
ASN1_GEN_STR("NULL", V_ASN1_NULL),
@@ -568,7 +565,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 +582,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 +593,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 +615,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 +639,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 +672,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,31 +687,34 @@ 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;
atmp->value.asn1_string->length = rdlen;
atmp->value.asn1_string->type = utype;
- } else if (format == ASN1_GEN_FORMAT_ASCII)
- ASN1_STRING_set(atmp->value.asn1_string, str, -1);
- else if ((format == ASN1_GEN_FORMAT_BITLIST)
+ } else if (format == ASN1_GEN_FORMAT_ASCII) {
+ if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+ } else if ((format == ASN1_GEN_FORMAT_BITLIST)
&& (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 +727,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 +753,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_parse.c
index a32fa47f2206..6a4618d253d5 100644
--- a/crypto/asn1/asn1_par.c
+++ b/crypto/asn1/asn1_parse.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2021 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
@@ -17,25 +17,47 @@
#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 int asn1_print_info(BIO *bp, long offset, int depth, int hl, long len,
+ int tag, int xclass, int constructed, int indent)
{
- static const char fmt[] = "%-18s";
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 (BIO_write(bp, p, 6) < 6)
- goto err;
- BIO_indent(bp, indent, 128);
+ 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);
@@ -48,11 +70,14 @@ static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
else
p = ASN1_tag2str(tag);
- if (BIO_printf(bp, fmt, p) <= 0)
- goto err;
- return 1;
+ i = (BIO_printf(bp, "%-18s", p) > 0);
err:
- return 0;
+ 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)
@@ -92,9 +117,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
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;
+ BIO_puts(bp, "Error in encoding\n");
goto end;
}
hl = (p - op);
@@ -102,19 +125,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
/*
* 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))
+ 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;
@@ -124,7 +136,6 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
goto end;
if (len > length) {
BIO_printf(bp, "length is greater than %ld\n", length);
- ret = 0;
goto end;
}
if ((j == 0x21) && (len == 0)) {
@@ -132,10 +143,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
r = asn1_parse2(bp, &p, (long)(tot - p),
offset + (p - *pp), depth + 1,
indent, dump);
- if (r == 0) {
- ret = 0;
+ if (r == 0)
goto end;
- }
if ((r == 2) || (p >= tot)) {
len = p - sp;
break;
@@ -149,10 +158,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
r = asn1_parse2(bp, &p, tmp,
offset + (p - *pp), depth + 1,
indent, dump);
- if (r == 0) {
- ret = 0;
+ if (r == 0)
goto end;
- }
tmp -= p - sp;
}
}
diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c
index 36853612b69c..c50665914e3c 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 {
@@ -89,8 +96,8 @@ int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
* internally
*/
else
- ASN1_item_i2d_bio(it, out, val);
- return 1;
+ rv = ASN1_item_i2d_bio(it, out, val);
+ 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,11 @@ 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_id_smime_ct_authEnvelopedData) {
+ msg_type = "authEnveloped-data";
+ } 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 +329,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 +353,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 +371,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 +396,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 +412,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 +428,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 +445,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 +455,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 +480,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 +490,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 */
@@ -490,13 +518,21 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
int len;
char linebuf[MAX_SMLEN];
int ret;
+
+ if (in == NULL || out == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
/*
* Buffer output so we don't write one line at a time. This is useful
* 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 +543,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 +554,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 +579,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 +607,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 +624,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 +635,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 +649,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 +786,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 +810,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 +831,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 +917,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 +926,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 +1007,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..9aaab8a269d3 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;
}
}
@@ -67,6 +67,10 @@ static int do_create(const char *value, const char *name)
if (p == NULL) {
ln = name;
ostr = value;
+ } else if (p == value) {
+ /* we started with a leading comma */
+ ln = name;
+ ostr = p + 1;
} else {
ln = value;
ostr = p + 1;
@@ -84,7 +88,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..1208d5663d25 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
}
}
@@ -72,6 +72,8 @@ static int do_tcreate(const char *value, const char *name)
goto err;
for (i = 0; i < sk_CONF_VALUE_num(lst); i++) {
cnf = sk_CONF_VALUE_value(lst, i);
+ if (cnf->value == NULL)
+ goto err;
if (strcmp(cnf->name, "min") == 0) {
tbl_min = strtoul(cnf->value, &eptr, 0);
if (*eptr)
@@ -96,17 +98,19 @@ 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 != NULL ? cnf->value
+ : 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..2389264f17da 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-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,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 {
@@ -29,12 +29,12 @@ ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
OPENSSL_free(octmp->data);
octmp->data = NULL;
- if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) {
- ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR);
+ if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) <= 0) {
+ 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..fb2e040c7c56 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
@@ -550,6 +571,9 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
return -1;
break;
+ case V_ASN1_UNDEF:
+ return -2;
+
case V_ASN1_NULL:
cont = NULL;
len = 0;
@@ -574,15 +598,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..f8068832ab67 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,18 @@ 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 */
+ OPENSSL_assert(embed == 0);
+ *pval = NULL;
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 +107,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 +123,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 +138,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 +172,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 +200,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..2c4a8d4b4ee8 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,75 @@ 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;
+ if (!X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp)) {
+ X509_ALGOR_free(*palg);
+ *palg = NULL;
+ goto err;
+ }
+ 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.c b/crypto/async/arch/async_win.c
new file mode 100644
index 000000000000..0b276fd504d8
--- /dev/null
+++ b/crypto/async/arch/async_win.c
@@ -0,0 +1,59 @@
+/*
+ * 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 must be the first #include file */
+#include "../async_local.h"
+
+#ifdef ASYNC_WIN
+
+# include <windows.h>
+# include "internal/cryptlib.h"
+
+int ASYNC_is_capable(void)
+{
+ return 1;
+}
+
+void async_local_cleanup(void)
+{
+ async_ctx *ctx = async_get_ctx();
+ if (ctx != NULL) {
+ async_fibre *fibre = &ctx->dispatcher;
+ if (fibre != NULL && fibre->fibre != NULL && fibre->converted) {
+ ConvertFiberToThread();
+ fibre->fibre = NULL;
+ }
+ }
+}
+
+int async_fibre_init_dispatcher(async_fibre *fibre)
+{
+# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+ fibre->fibre = ConvertThreadToFiberEx(NULL, FIBER_FLAG_FLOAT_SWITCH);
+# else
+ fibre->fibre = ConvertThreadToFiber(NULL);
+# endif
+ if (fibre->fibre == NULL) {
+ fibre->converted = 0;
+ fibre->fibre = GetCurrentFiber();
+ if (fibre->fibre == NULL)
+ return 0;
+ } else {
+ fibre->converted = 1;
+ }
+
+ return 1;
+}
+
+VOID CALLBACK async_start_func_win(PVOID unused)
+{
+ async_start_func();
+}
+
+#endif
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/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..2409c9db97cc
--- /dev/null
+++ b/crypto/bio/bf_readbuff.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with 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 (buf == NULL || size == 0)
+ return 0;
+ --size; /* the passed in size includes the terminator - so remove it here */
+ ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+
+ if (ctx == NULL || b->next_bio == NULL)
+ return 0;
+ 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/b_addr.c b/crypto/bio/bio_addr.c
index 0af7a330bc68..d462f424d3a4 100644
--- a/crypto/bio/b_addr.c
+++ b/crypto/bio/bio_addr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,16 @@
# 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>
@@ -44,7 +54,7 @@ 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);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -211,13 +221,12 @@ static int addr_strings(const BIO_ADDR *ap, int numeric,
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);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling getnameinfo()");
} else
# endif
{
- BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
- ERR_add_error_data(1, gai_strerror(ret));
+ ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, gai_strerror(ret));
}
return 0;
}
@@ -258,7 +267,7 @@ static int addr_strings(const BIO_ADDR *ap, int numeric,
OPENSSL_free(*service);
*service = NULL;
}
- BIOerr(BIO_F_ADDR_STRINGS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -538,20 +547,25 @@ int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
*service = NULL;
} else {
*service = OPENSSL_strndup(p, pl);
- if (*service == NULL)
+ if (*service == NULL) {
+ if (h != NULL && host != NULL) {
+ OPENSSL_free(*host);
+ *host = NULL;
+ }
goto memerr;
+ }
}
}
return 1;
amb_err:
- BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
return 0;
spec_err:
- BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE);
return 0;
memerr:
- BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -570,7 +584,7 @@ static int addrinfo_wrap(int family, int socktype,
BIO_ADDRINFO **bai)
{
if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) {
- BIOerr(BIO_F_ADDRINFO_WRAP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -607,8 +621,6 @@ static int addrinfo_wrap(int family, int socktype,
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;
}
@@ -621,8 +633,8 @@ int BIO_lookup(const char *host, const char *service,
}
/*-
- * BIO_lookup_ex - look up the node and service you want to connect to.
- * @node: the node you want to connect to.
+ * 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
@@ -635,7 +647,7 @@ int BIO_lookup(const char *host, const char *service,
* 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.
+ * 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.
@@ -660,7 +672,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
#endif
break;
default:
- BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
return 0;
}
@@ -669,7 +681,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
return 1;
else
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
#endif
@@ -706,13 +718,14 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
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);
+ 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:
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
break;
# endif
case 0:
@@ -727,8 +740,8 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
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));
+ ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB,
+ gai_strerror(old_ret ? old_ret : gai_ret));
break;
}
} else {
@@ -769,12 +782,13 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
#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;
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
}
- CRYPTO_THREAD_write_lock(bio_lookup_lock);
+ if (!CRYPTO_THREAD_write_lock(bio_lookup_lock))
+ return 0;
+
he_fallback_address = INADDR_ANY;
if (host == NULL) {
he = &he_fallback;
@@ -788,7 +802,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
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);
+ ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR);
ret = 0;
goto err;
}
@@ -810,12 +824,15 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
*/
# if defined(OPENSSL_SYS_VXWORKS)
/* h_errno doesn't exist on VxWorks */
- SYSerr(SYS_F_GETHOSTBYNAME, 1000 );
+ ERR_raise_data(ERR_LIB_SYS, 1000,
+ "calling gethostbyname()");
# else
- SYSerr(SYS_F_GETHOSTBYNAME, 1000 + h_errno);
+ ERR_raise_data(ERR_LIB_SYS, 1000 + h_errno,
+ "calling gethostbyname()");
# endif
#else
- SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError());
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling gethostbyname()");
#endif
ret = 0;
goto err;
@@ -861,15 +878,12 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
se = getservbyname(service, proto);
if (se == NULL) {
-#ifndef OPENSSL_SYS_WINDOWS
- SYSerr(SYS_F_GETSERVBYNAME, errno);
-#else
- SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError());
-#endif
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling getservbyname()");
goto err;
}
} else {
- BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_MALFORMED_HOST_OR_SERVICE);
+ ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE);
goto err;
}
}
@@ -911,7 +925,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
addrinfo_malloc_err:
BIO_ADDRINFO_free(*res);
*res = NULL;
- BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
ret = 0;
goto err;
}
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/b_dump.c b/crypto/bio/bio_dump.c
index f175e244b233..04191a653054 100644
--- a/crypto/bio/b_dump.c
+++ b/crypto/bio/bio_dump.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,15 +20,16 @@
#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)
+ 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 char *s, int len, int indent)
+ void *u, const void *v, int len, int indent)
{
- int ret = 0;
+ const unsigned char *s = v;
+ int res, ret = 0;
char buf[288 + 1];
int i, j, rows, n;
unsigned char ch;
@@ -46,12 +47,14 @@ int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
for (i = 0; i < rows; i++) {
n = BIO_snprintf(buf, sizeof(buf), "%*s%04x - ", indent, "",
i * dump_width);
+ if (n < 0)
+ return -1;
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;
+ ch = *(s + i * dump_width + j) & 0xff;
BIO_snprintf(buf + n, 4, "%02x%c", ch,
j == 7 ? '-' : ' ');
}
@@ -66,7 +69,7 @@ int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
if (((i * dump_width) + j) >= len)
break;
if (SPACE(buf, n, 1)) {
- ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
+ ch = *(s + i * dump_width + j) & 0xff;
#ifndef CHARSET_EBCDIC
buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.';
#else
@@ -85,7 +88,10 @@ int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u),
* 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);
+ res = cb((void *)buf, n, u);
+ if (res < 0)
+ return res;
+ ret += res;
}
return ret;
}
@@ -96,12 +102,12 @@ 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)
+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 char *s, int len, int indent)
+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);
}
@@ -112,19 +118,20 @@ 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)
+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 char *s, int len, int indent)
+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, unsigned char *data,
+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)
@@ -134,7 +141,7 @@ int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
if (i && !j)
BIO_printf(out, "%*s", indent, "");
- BIO_printf(out, "%02X:", data[i]);
+ BIO_printf(out, "%02X:", d[i]);
j = (j + 1) % width;
if (!j)
@@ -143,6 +150,6 @@ int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
if (i && !j)
BIO_printf(out, "%*s", indent, "");
- BIO_printf(out, "%02X", data[datalen - 1]);
+ 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..245a75afa1b8 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
@@ -712,7 +784,7 @@ BIO *BIO_dup_chain(BIO *in)
/* This will let SSL_s_sock() work with stdin/stdout */
new_bio->num = bio->num;
- if (!BIO_dup_state(bio, (char *)new_bio)) {
+ if (BIO_dup_state(bio, (char *)new_bio) <= 0) {
BIO_free(new_bio);
goto err;
}
@@ -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,131 @@ 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) {
+ int ret = BIO_socket_wait(fd, BIO_should_read(bio), max_time);
+
+ if (ret != -1)
+ return ret;
+ }
+#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/b_print.c b/crypto/bio/bio_print.c
index 45d4e9f004b1..1934a6884251 100644
--- a/crypto/bio/b_print.c
+++ b/crypto/bio/bio_print.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 "crypto/ctype.h"
#include "internal/numbers.h"
#include <openssl/bio.h>
-#include <openssl/opensslconf.h>
+#include <openssl/configuration.h>
/*
* Copyright Patrick Powell 1995
@@ -344,7 +344,7 @@ _dopr(char **sbuffer,
break;
case 'w':
/* not supported yet, treat as next char */
- ch = *format++;
+ format++;
break;
default:
/* unknown, skip */
@@ -535,6 +535,10 @@ static LDOUBLE abs_val(LDOUBLE value)
LDOUBLE result = value;
if (value < 0)
result = -value;
+ if (result > 0 && result / 2 == result) /* INF */
+ result = 0;
+ else if (result != result) /* NAN */
+ result = 0;
return result;
}
@@ -590,6 +594,9 @@ fmtfp(char **sbuffer,
signvalue = '+';
else if (flags & DP_F_SPACE)
signvalue = ' ';
+ ufvalue = abs_val(fvalue);
+ if (ufvalue == 0 && fvalue != 0) /* INF or NAN? */
+ signvalue = '?';
/*
* G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT
@@ -597,12 +604,12 @@ fmtfp(char **sbuffer,
* that from here on.
*/
if (style == G_FORMAT) {
- if (fvalue == 0.0) {
+ if (ufvalue == 0.0) {
realstyle = F_FORMAT;
- } else if (fvalue < 0.0001) {
+ } else if (ufvalue < 0.0001) {
realstyle = E_FORMAT;
- } else if ((max == 0 && fvalue >= 10)
- || (max > 0 && fvalue >= pow_10(max))) {
+ } else if ((max == 0 && ufvalue >= 10)
+ || (max > 0 && ufvalue >= pow_10(max))) {
realstyle = E_FORMAT;
} else {
realstyle = F_FORMAT;
@@ -612,9 +619,9 @@ fmtfp(char **sbuffer,
}
if (style != F_FORMAT) {
- tmpvalue = fvalue;
+ tmpvalue = ufvalue;
/* Calculate the exponent */
- if (fvalue != 0.0) {
+ if (ufvalue != 0.0) {
while (tmpvalue < 1) {
tmpvalue *= 10;
exp--;
@@ -638,6 +645,7 @@ fmtfp(char **sbuffer,
/*
* Should not happen. If we're in F_FORMAT then exp < max?
*/
+ (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0');
return 0;
}
} else {
@@ -650,15 +658,16 @@ fmtfp(char **sbuffer,
}
}
if (realstyle == E_FORMAT)
- fvalue = tmpvalue;
+ ufvalue = 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;
@@ -722,8 +731,10 @@ fmtfp(char **sbuffer,
tmpexp = (tmpexp / 10);
} while (tmpexp > 0 && eplace < (int)sizeof(econvert));
/* Exponent is huge!! Too big to print */
- if (tmpexp > 0)
+ 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';
@@ -844,7 +855,7 @@ doapr_outch(char **sbuffer,
*maxlen += BUFFER_INC;
if (*buffer == NULL) {
if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
- BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
if (*currlen > 0) {
@@ -855,9 +866,12 @@ doapr_outch(char **sbuffer,
*sbuffer = NULL;
} else {
char *tmpbuf;
+
tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
- if (tmpbuf == NULL)
+ if (tmpbuf == NULL) {
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return 0;
+ }
*buffer = tmpbuf;
}
}
@@ -949,6 +963,5 @@ int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
* been large enough.)
*/
return -1;
- else
- return (retlen <= INT_MAX) ? (int)retlen : -1;
+ return (retlen <= INT_MAX) ? (int)retlen : -1;
}
diff --git a/crypto/bio/b_sock.c b/crypto/bio/bio_sock.c
index df431e6d523d..84496de6f6bd 100644
--- a/crypto/bio/b_sock.c
+++ b/crypto/bio/bio_sock.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 <stdio.h>
#include <stdlib.h>
-#include <errno.h>
#include "bio_local.h"
#ifndef OPENSSL_NO_SOCK
# define SOCKET_PROTOCOL IPPROTO_TCP
@@ -24,7 +23,26 @@
static int wsa_init_done = 0;
# endif
-# if OPENSSL_API_COMPAT < 0x10100000L
+# 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;
@@ -37,8 +55,7 @@ int BIO_get_host_ip(const char *str, unsigned char *ip)
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);
+ 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
@@ -61,7 +78,7 @@ int BIO_get_port(const char *str, unsigned short *port_ptr)
int ret = 0;
if (str == NULL) {
- BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED);
+ ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED);
return 0;
}
@@ -70,8 +87,7 @@ int BIO_get_port(const char *str, unsigned short *port_ptr)
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);
+ 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;
@@ -103,7 +119,7 @@ int BIO_sock_error(int sock)
return j;
}
-# if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
struct hostent *BIO_gethostbyname(const char *name)
{
/*
@@ -120,8 +136,6 @@ int BIO_sock_init(void)
static struct WSAData wsa_state;
if (!wsa_init_done) {
- int err;
-
wsa_init_done = 1;
memset(&wsa_state, 0, sizeof(wsa_state));
/*
@@ -131,9 +145,9 @@ int BIO_sock_init(void)
* 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);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling wsastartup()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP);
return -1;
}
}
@@ -192,11 +206,12 @@ int BIO_socket_ioctl(int fd, long type, void *arg)
i = ioctlsocket(fd, type, ARG);
# endif /* __DJGPP__ */
if (i < 0)
- SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error());
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling ioctlsocket()");
return i;
}
-# if OPENSSL_API_COMPAT < 0x10100000L
+# ifndef OPENSSL_NO_DEPRECATED_1_1_0
int BIO_get_accept_socket(char *host, int bind_mode)
{
int s = INVALID_SOCKET;
@@ -207,7 +222,7 @@ int BIO_get_accept_socket(char *host, int bind_mode)
return INVALID_SOCKET;
if (BIO_sock_init() != 1)
- return INVALID_SOCKET;
+ goto err;
if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
goto err;
@@ -243,8 +258,9 @@ int BIO_accept(int sock, char **ip_port)
ret = -2;
goto end;
}
- SYSerr(SYS_F_ACCEPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling accept()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
goto end;
}
@@ -257,7 +273,7 @@ int BIO_accept(int sock, char **ip_port)
*ip_port = NULL;
if (*ip_port == NULL) {
- BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
BIO_closesocket(ret);
ret = (int)INVALID_SOCKET;
} else {
@@ -308,7 +324,8 @@ int BIO_socket_nbio(int s, int mode)
l = fcntl(s, F_GETFL, 0);
if (l == -1) {
- SYSerr(SYS_F_FCNTL, get_last_sys_error());
+ ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
+ "calling fcntl()");
ret = -1;
} else {
# if defined(O_NONBLOCK)
@@ -326,12 +343,13 @@ int BIO_socket_nbio(int s, int mode)
ret = fcntl(s, F_SETFL, l);
if (ret < 0) {
- SYSerr(SYS_F_FCNTL, get_last_sys_error());
+ 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. */
- BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT);
+ ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT);
# endif
return (ret == 0);
@@ -349,21 +367,53 @@ int BIO_sock_info(int sock,
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);
+ 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)) {
- BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
+ ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
return 0;
}
}
break;
default:
- BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE);
+ 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;
+
+#ifdef _WIN32
+ if ((SOCKET)fd == INVALID_SOCKET)
+#else
+ if (fd < 0 || fd >= FD_SETSIZE)
#endif
+ 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/b_sock2.c b/crypto/bio/bio_sock2.c
index 104ff31b0d2e..8bdad0c0b6ae 100644
--- a/crypto/bio/b_sock2.c
+++ b/crypto/bio/bio_sock2.c
@@ -1,7 +1,7 @@
/*
- * 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
@@ -12,6 +12,7 @@
#include <errno.h>
#include "bio_local.h"
+#include "internal/ktls.h"
#include <openssl/err.h>
@@ -46,8 +47,9 @@ int BIO_socket(int domain, int socktype, int protocol, int options)
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);
+ 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;
}
@@ -79,7 +81,7 @@ 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);
+ ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
return 0;
}
@@ -89,8 +91,9 @@ int BIO_connect(int sock, const BIO_ADDR *addr, int options)
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);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
return 0;
}
}
@@ -98,8 +101,9 @@ int BIO_connect(int sock, const BIO_ADDR *addr, int options)
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);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
return 0;
}
}
@@ -107,11 +111,21 @@ int BIO_connect(int sock, const BIO_ADDR *addr, int options)
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);
+ 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;
}
@@ -138,7 +152,7 @@ int BIO_bind(int sock, const BIO_ADDR *addr, int options)
# endif
if (sock == -1) {
- BIOerr(BIO_F_BIO_BIND, BIO_R_INVALID_SOCKET);
+ ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
return 0;
}
@@ -150,16 +164,18 @@ int BIO_bind(int sock, const BIO_ADDR *addr, int options)
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);
+ 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) {
- SYSerr(SYS_F_BIND, get_last_socket_error());
- BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_BIND_SOCKET);
+ 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;
}
@@ -210,15 +226,16 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options)
socklen_t socktype_len = sizeof(socktype);
if (sock == -1) {
- BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET);
+ 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)) {
- SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error());
- BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling getsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE);
return 0;
}
@@ -228,8 +245,9 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options)
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);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
return 0;
}
}
@@ -237,8 +255,9 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options)
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);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
return 0;
}
}
@@ -253,8 +272,9 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options)
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);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling setsockopt()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY);
return 0;
}
}
@@ -264,8 +284,9 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int 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);
+ 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;
}
@@ -291,8 +312,9 @@ int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
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);
+ ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
+ "calling accept()");
+ ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
}
return INVALID_SOCKET;
}
@@ -311,7 +333,7 @@ int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
*/
int BIO_closesocket(int sock)
{
- if (closesocket(sock) < 0)
+ if (sock < 0 || closesocket(sock) < 0)
return 0;
return 1;
}
diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c
index 4461eae2333d..8870831039e9 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-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
*/
+#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.
@@ -559,7 +566,7 @@ BIO *BIO_new_accept(const char *str)
ret = BIO_new(BIO_s_accept());
if (ret == NULL)
return NULL;
- if (BIO_set_accept_name(ret, str))
+ if (BIO_set_accept_name(ret, str) > 0)
return ret;
BIO_free(ret);
return NULL;
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..63b30e300fec 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);
@@ -280,7 +281,7 @@ static void xsyslog(BIO *bp, int priority, const char *string)
break;
}
- sprintf(pidbuf, "[%lu] ", GetCurrentProcessId());
+ BIO_snprintf(pidbuf, sizeof(pidbuf), "[%lu] ", GetCurrentProcessId());
lpszStrings[0] = pidbuf;
lpszStrings[1] = string;
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
deleted file mode 100644
index 5d5c4fa99fa1..000000000000
--- a/crypto/bn/README.pod
+++ /dev/null
@@ -1,241 +0,0 @@
-=pod
-
-=head1 NAME
-
-bn_mul_words, bn_mul_add_words, bn_sqr_words, bn_div_words,
-bn_add_words, bn_sub_words, bn_mul_comba4, bn_mul_comba8,
-bn_sqr_comba4, bn_sqr_comba8, bn_cmp_words, bn_mul_normal,
-bn_mul_low_normal, bn_mul_recursive, bn_mul_part_recursive,
-bn_mul_low_recursive, bn_sqr_normal, bn_sqr_recursive,
-bn_expand, bn_wexpand, bn_expand2, bn_fix_top, bn_check_top,
-bn_print, bn_dump, bn_set_max, bn_set_high, bn_set_low - BIGNUM
-library internal functions
-
-=head1 SYNOPSIS
-
- #include <openssl/bn.h>
-
- BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
- BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num,
- BN_ULONG w);
- void bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num);
- BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
- BN_ULONG bn_add_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,
- int num);
- BN_ULONG bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,
- int num);
-
- void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
- void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
- void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a);
- void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a);
-
- int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n);
-
- void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b,
- int nb);
- void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n);
- void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
- int dna, int dnb, BN_ULONG *tmp);
- void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b,
- int n, int tna, int tnb, BN_ULONG *tmp);
- void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b,
- int n2, BN_ULONG *tmp);
-
- void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp);
- void bn_sqr_recursive(BN_ULONG *r, BN_ULONG *a, int n2, BN_ULONG *tmp);
-
- void mul(BN_ULONG r, BN_ULONG a, BN_ULONG w, BN_ULONG c);
- void mul_add(BN_ULONG r, BN_ULONG a, BN_ULONG w, BN_ULONG c);
- void sqr(BN_ULONG r0, BN_ULONG r1, BN_ULONG a);
-
- BIGNUM *bn_expand(BIGNUM *a, int bits);
- BIGNUM *bn_wexpand(BIGNUM *a, int n);
- BIGNUM *bn_expand2(BIGNUM *a, int n);
- void bn_fix_top(BIGNUM *a);
-
- void bn_check_top(BIGNUM *a);
- void bn_print(BIGNUM *a);
- void bn_dump(BN_ULONG *d, int n);
- void bn_set_max(BIGNUM *a);
- void bn_set_high(BIGNUM *r, BIGNUM *a, int n);
- void bn_set_low(BIGNUM *r, BIGNUM *a, int n);
-
-=head1 DESCRIPTION
-
-This page documents the internal functions used by the OpenSSL
-B<BIGNUM> implementation. They are described here to facilitate
-debugging and extending the library. They are I<not> to be used by
-applications.
-
-=head2 The BIGNUM structure
-
- typedef struct bignum_st BIGNUM;
-
- struct bignum_st
- {
- BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */
- int top; /* Index of last used d +1. */
- /* The next are internal book keeping for bn_expand. */
- int dmax; /* Size of the d array. */
- int neg; /* one if the number is negative */
- int flags;
- };
-
-
-The integer value is stored in B<d>, a malloc()ed array of words (B<BN_ULONG>),
-least significant word first. A B<BN_ULONG> can be either 16, 32 or 64 bits
-in size, depending on the 'number of bits' (B<BITS2>) specified in
-C<openssl/bn.h>.
-
-B<dmax> is the size of the B<d> array that has been allocated. B<top>
-is the number of words being used, so for a value of 4, bn.d[0]=4 and
-bn.top=1. B<neg> is 1 if the number is negative. When a B<BIGNUM> is
-B<0>, the B<d> field can be B<NULL> and B<top> == B<0>.
-
-B<flags> is a bit field of flags which are defined in C<openssl/bn.h>. The
-flags begin with B<BN_FLG_>. The macros BN_set_flags(b, n) and
-BN_get_flags(b, n) exist to enable or fetch flag(s) B<n> from B<BIGNUM>
-structure B<b>.
-
-Various routines in this library require the use of temporary
-B<BIGNUM> variables during their execution. 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. This structure contains B<BN_CTX_NUM> B<BIGNUM>s, see
-L<BN_CTX_start(3)>.
-
-=head2 Low-level arithmetic operations
-
-These functions are implemented in C and for several platforms in
-assembly language:
-
-bn_mul_words(B<rp>, B<ap>, B<num>, B<w>) operates on the B<num> word
-arrays B<rp> and B<ap>. It computes B<ap> * B<w>, places the result
-in B<rp>, and returns the high word (carry).
-
-bn_mul_add_words(B<rp>, B<ap>, B<num>, B<w>) operates on the B<num>
-word arrays B<rp> and B<ap>. It computes B<ap> * B<w> + B<rp>, places
-the result in B<rp>, and returns the high word (carry).
-
-bn_sqr_words(B<rp>, B<ap>, B<n>) operates on the B<num> word array
-B<ap> and the 2*B<num> word array B<ap>. It computes B<ap> * B<ap>
-word-wise, and places the low and high bytes of the result in B<rp>.
-
-bn_div_words(B<h>, B<l>, B<d>) divides the two word number (B<h>, B<l>)
-by B<d> and returns the result.
-
-bn_add_words(B<rp>, B<ap>, B<bp>, B<num>) operates on the B<num> word
-arrays B<ap>, B<bp> and B<rp>. It computes B<ap> + B<bp>, places the
-result in B<rp>, and returns the high word (carry).
-
-bn_sub_words(B<rp>, B<ap>, B<bp>, B<num>) operates on the B<num> word
-arrays B<ap>, B<bp> and B<rp>. It computes B<ap> - B<bp>, places the
-result in B<rp>, and returns the carry (1 if B<bp> E<gt> B<ap>, 0
-otherwise).
-
-bn_mul_comba4(B<r>, B<a>, B<b>) operates on the 4 word arrays B<a> and
-B<b> and the 8 word array B<r>. It computes B<a>*B<b> and places the
-result in B<r>.
-
-bn_mul_comba8(B<r>, B<a>, B<b>) operates on the 8 word arrays B<a> and
-B<b> and the 16 word array B<r>. It computes B<a>*B<b> and places the
-result in B<r>.
-
-bn_sqr_comba4(B<r>, B<a>, B<b>) operates on the 4 word arrays B<a> and
-B<b> and the 8 word array B<r>.
-
-bn_sqr_comba8(B<r>, B<a>, B<b>) operates on the 8 word arrays B<a> and
-B<b> and the 16 word array B<r>.
-
-The following functions are implemented in C:
-
-bn_cmp_words(B<a>, B<b>, B<n>) operates on the B<n> word arrays B<a>
-and B<b>. It returns 1, 0 and -1 if B<a> is greater than, equal and
-less than B<b>.
-
-bn_mul_normal(B<r>, B<a>, B<na>, B<b>, B<nb>) operates on the B<na>
-word array B<a>, the B<nb> word array B<b> and the B<na>+B<nb> word
-array B<r>. It computes B<a>*B<b> and places the result in B<r>.
-
-bn_mul_low_normal(B<r>, B<a>, B<b>, B<n>) operates on the B<n> word
-arrays B<r>, B<a> and B<b>. It computes the B<n> low words of
-B<a>*B<b> and places the result in B<r>.
-
-bn_mul_recursive(B<r>, B<a>, B<b>, B<n2>, B<dna>, B<dnb>, B<t>) operates
-on the word arrays B<a> and B<b> of length B<n2>+B<dna> and B<n2>+B<dnb>
-(B<dna> and B<dnb> are currently allowed to be 0 or negative) and the 2*B<n2>
-word arrays B<r> and B<t>. B<n2> must be a power of 2. It computes
-B<a>*B<b> and places the result in B<r>.
-
-bn_mul_part_recursive(B<r>, B<a>, B<b>, B<n>, B<tna>, B<tnb>, B<tmp>)
-operates on the word arrays B<a> and B<b> of length B<n>+B<tna> and
-B<n>+B<tnb> and the 4*B<n> word arrays B<r> and B<tmp>.
-
-bn_mul_low_recursive(B<r>, B<a>, B<b>, B<n2>, B<tmp>) operates on the
-B<n2> word arrays B<r> and B<tmp> and the B<n2>/2 word arrays B<a>
-and B<b>.
-
-BN_mul() calls bn_mul_normal(), or an optimized implementation if the
-factors have the same size: bn_mul_comba8() is used if they are 8
-words long, bn_mul_recursive() if they are larger than
-B<BN_MULL_SIZE_NORMAL> and the size is an exact multiple of the word
-size, and bn_mul_part_recursive() for others that are larger than
-B<BN_MULL_SIZE_NORMAL>.
-
-bn_sqr_normal(B<r>, B<a>, B<n>, B<tmp>) operates on the B<n> word array
-B<a> and the 2*B<n> word arrays B<tmp> and B<r>.
-
-The implementations use the following macros which, depending on the
-architecture, may use "long long" C operations or inline assembler.
-They are defined in C<bn_local.h>.
-
-mul(B<r>, B<a>, B<w>, B<c>) computes B<w>*B<a>+B<c> and places the
-low word of the result in B<r> and the high word in B<c>.
-
-mul_add(B<r>, B<a>, B<w>, B<c>) computes B<w>*B<a>+B<r>+B<c> and
-places the low word of the result in B<r> and the high word in B<c>.
-
-sqr(B<r0>, B<r1>, B<a>) computes B<a>*B<a> and places the low word
-of the result in B<r0> and the high word in B<r1>.
-
-=head2 Size changes
-
-bn_expand() ensures that B<b> has enough space for a B<bits> bit
-number. bn_wexpand() ensures that B<b> has enough space for an
-B<n> word number. If the number has to be expanded, both macros
-call bn_expand2(), which allocates a new B<d> array and copies the
-data. They return B<NULL> on error, B<b> otherwise.
-
-The bn_fix_top() macro reduces B<a-E<gt>top> to point to the most
-significant non-zero word plus one when B<a> has shrunk.
-
-=head2 Debugging
-
-bn_check_top() verifies that C<((a)-E<gt>top E<gt>= 0 && (a)-E<gt>top
-E<lt>= (a)-E<gt>dmax)>. A violation will cause the program to abort.
-
-bn_print() prints B<a> to stderr. bn_dump() prints B<n> words at B<d>
-(in reverse order, i.e. most significant word first) to stderr.
-
-bn_set_max() makes B<a> a static number with a B<dmax> of its current size.
-This is used by bn_set_low() and bn_set_high() to make B<r> a read-only
-B<BIGNUM> that contains the B<n> low or high words of B<a>.
-
-If B<BN_DEBUG> is not defined, bn_check_top(), bn_print(), bn_dump()
-and bn_set_max() are defined as empty macros.
-
-=head1 SEE ALSO
-
-L<bn(3)>
-
-=head1 COPYRIGHT
-
-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
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/crypto/bn/asm/alpha-mont.pl b/crypto/bn/asm/alpha-mont.pl
new file mode 100644
index 000000000000..9d362a6f65ed
--- /dev/null
+++ b/crypto/bn/asm/alpha-mont.pl
@@ -0,0 +1,327 @@
+#! /usr/bin/env perl
+# 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
+
+#
+# ====================================================================
+# 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/.
+# ====================================================================
+#
+# On 21264 RSA sign performance improves by 70/35/20/15 percent for
+# 512/1024/2048/4096 bit key lengths. This is against vendor compiler
+# instructed to '-tune host' code with in-line assembler. Other
+# benchmarks improve by 15-20%. To anchor it to something else, the
+# code provides approximately the same performance per GHz as AMD64.
+# I.e. if you compare 1GHz 21264 and 2GHz Opteron, you'll observe ~2x
+# difference.
+
+$output=pop and open STDOUT,">$output";
+
+# int bn_mul_mont(
+$rp="a0"; # BN_ULONG *rp,
+$ap="a1"; # const BN_ULONG *ap,
+$bp="a2"; # const BN_ULONG *bp,
+$np="a3"; # const BN_ULONG *np,
+$n0="a4"; # const BN_ULONG *n0,
+$num="a5"; # int num);
+
+$lo0="t0";
+$hi0="t1";
+$lo1="t2";
+$hi1="t3";
+$aj="t4";
+$bi="t5";
+$nj="t6";
+$tp="t7";
+$alo="t8";
+$ahi="t9";
+$nlo="t10";
+$nhi="t11";
+$tj="t12";
+$i="s3";
+$j="s4";
+$m1="s5";
+
+$code=<<___;
+#ifdef __linux__
+#include <asm/regdef.h>
+#else
+#include <asm.h>
+#include <regdef.h>
+#endif
+
+.text
+
+.set noat
+.set noreorder
+
+.globl bn_mul_mont
+.align 5
+.ent bn_mul_mont
+bn_mul_mont:
+ lda sp,-48(sp)
+ stq ra,0(sp)
+ stq s3,8(sp)
+ stq s4,16(sp)
+ stq s5,24(sp)
+ stq fp,32(sp)
+ mov sp,fp
+ .mask 0x0400f000,-48
+ .frame fp,48,ra
+ .prologue 0
+
+ .align 4
+ .set reorder
+ sextl $num,$num
+ mov 0,v0
+ cmplt $num,4,AT
+ bne AT,.Lexit
+
+ ldq $hi0,0($ap) # ap[0]
+ s8addq $num,16,AT
+ ldq $aj,8($ap)
+ subq sp,AT,sp
+ ldq $bi,0($bp) # bp[0]
+ lda AT,-4096(zero) # mov -4096,AT
+ ldq $n0,0($n0)
+ and sp,AT,sp
+
+ mulq $hi0,$bi,$lo0
+ ldq $hi1,0($np) # np[0]
+ umulh $hi0,$bi,$hi0
+ ldq $nj,8($np)
+
+ mulq $lo0,$n0,$m1
+
+ mulq $hi1,$m1,$lo1
+ umulh $hi1,$m1,$hi1
+
+ addq $lo1,$lo0,$lo1
+ cmpult $lo1,$lo0,AT
+ addq $hi1,AT,$hi1
+
+ mulq $aj,$bi,$alo
+ mov 2,$j
+ umulh $aj,$bi,$ahi
+ mov sp,$tp
+
+ mulq $nj,$m1,$nlo
+ s8addq $j,$ap,$aj
+ umulh $nj,$m1,$nhi
+ s8addq $j,$np,$nj
+.align 4
+.L1st:
+ .set noreorder
+ ldq $aj,0($aj)
+ addl $j,1,$j
+ ldq $nj,0($nj)
+ lda $tp,8($tp)
+
+ addq $alo,$hi0,$lo0
+ mulq $aj,$bi,$alo
+ cmpult $lo0,$hi0,AT
+ addq $nlo,$hi1,$lo1
+
+ mulq $nj,$m1,$nlo
+ addq $ahi,AT,$hi0
+ cmpult $lo1,$hi1,v0
+ cmplt $j,$num,$tj
+
+ umulh $aj,$bi,$ahi
+ addq $nhi,v0,$hi1
+ addq $lo1,$lo0,$lo1
+ s8addq $j,$ap,$aj
+
+ umulh $nj,$m1,$nhi
+ cmpult $lo1,$lo0,v0
+ addq $hi1,v0,$hi1
+ s8addq $j,$np,$nj
+
+ stq $lo1,-8($tp)
+ nop
+ unop
+ bne $tj,.L1st
+ .set reorder
+
+ addq $alo,$hi0,$lo0
+ addq $nlo,$hi1,$lo1
+ cmpult $lo0,$hi0,AT
+ cmpult $lo1,$hi1,v0
+ addq $ahi,AT,$hi0
+ addq $nhi,v0,$hi1
+
+ addq $lo1,$lo0,$lo1
+ cmpult $lo1,$lo0,v0
+ addq $hi1,v0,$hi1
+
+ stq $lo1,0($tp)
+
+ addq $hi1,$hi0,$hi1
+ cmpult $hi1,$hi0,AT
+ stq $hi1,8($tp)
+ stq AT,16($tp)
+
+ mov 1,$i
+.align 4
+.Louter:
+ s8addq $i,$bp,$bi
+ ldq $hi0,0($ap)
+ ldq $aj,8($ap)
+ ldq $bi,0($bi)
+ ldq $hi1,0($np)
+ ldq $nj,8($np)
+ ldq $tj,0(sp)
+
+ mulq $hi0,$bi,$lo0
+ umulh $hi0,$bi,$hi0
+
+ addq $lo0,$tj,$lo0
+ cmpult $lo0,$tj,AT
+ addq $hi0,AT,$hi0
+
+ mulq $lo0,$n0,$m1
+
+ mulq $hi1,$m1,$lo1
+ umulh $hi1,$m1,$hi1
+
+ addq $lo1,$lo0,$lo1
+ cmpult $lo1,$lo0,AT
+ mov 2,$j
+ addq $hi1,AT,$hi1
+
+ mulq $aj,$bi,$alo
+ mov sp,$tp
+ umulh $aj,$bi,$ahi
+
+ mulq $nj,$m1,$nlo
+ s8addq $j,$ap,$aj
+ umulh $nj,$m1,$nhi
+.align 4
+.Linner:
+ .set noreorder
+ ldq $tj,8($tp) #L0
+ nop #U1
+ ldq $aj,0($aj) #L1
+ s8addq $j,$np,$nj #U0
+
+ ldq $nj,0($nj) #L0
+ nop #U1
+ addq $alo,$hi0,$lo0 #L1
+ lda $tp,8($tp)
+
+ mulq $aj,$bi,$alo #U1
+ cmpult $lo0,$hi0,AT #L0
+ addq $nlo,$hi1,$lo1 #L1
+ addl $j,1,$j
+
+ mulq $nj,$m1,$nlo #U1
+ addq $ahi,AT,$hi0 #L0
+ addq $lo0,$tj,$lo0 #L1
+ cmpult $lo1,$hi1,v0 #U0
+
+ umulh $aj,$bi,$ahi #U1
+ cmpult $lo0,$tj,AT #L0
+ addq $lo1,$lo0,$lo1 #L1
+ addq $nhi,v0,$hi1 #U0
+
+ umulh $nj,$m1,$nhi #U1
+ s8addq $j,$ap,$aj #L0
+ cmpult $lo1,$lo0,v0 #L1
+ cmplt $j,$num,$tj #U0 # borrow $tj
+
+ addq $hi0,AT,$hi0 #L0
+ addq $hi1,v0,$hi1 #U1
+ stq $lo1,-8($tp) #L1
+ bne $tj,.Linner #U0
+ .set reorder
+
+ ldq $tj,8($tp)
+ addq $alo,$hi0,$lo0
+ addq $nlo,$hi1,$lo1
+ cmpult $lo0,$hi0,AT
+ cmpult $lo1,$hi1,v0
+ addq $ahi,AT,$hi0
+ addq $nhi,v0,$hi1
+
+ addq $lo0,$tj,$lo0
+ cmpult $lo0,$tj,AT
+ addq $hi0,AT,$hi0
+
+ ldq $tj,16($tp)
+ addq $lo1,$lo0,$j
+ cmpult $j,$lo0,v0
+ addq $hi1,v0,$hi1
+
+ addq $hi1,$hi0,$lo1
+ stq $j,0($tp)
+ cmpult $lo1,$hi0,$hi1
+ addq $lo1,$tj,$lo1
+ cmpult $lo1,$tj,AT
+ addl $i,1,$i
+ addq $hi1,AT,$hi1
+ stq $lo1,8($tp)
+ cmplt $i,$num,$tj # borrow $tj
+ stq $hi1,16($tp)
+ bne $tj,.Louter
+
+ s8addq $num,sp,$tj # &tp[num]
+ mov $rp,$bp # put rp aside
+ mov sp,$tp
+ mov sp,$ap
+ mov 0,$hi0 # clear borrow bit
+
+.align 4
+.Lsub: ldq $lo0,0($tp)
+ ldq $lo1,0($np)
+ lda $tp,8($tp)
+ lda $np,8($np)
+ subq $lo0,$lo1,$lo1 # tp[i]-np[i]
+ cmpult $lo0,$lo1,AT
+ subq $lo1,$hi0,$lo0
+ cmpult $lo1,$lo0,$hi0
+ or $hi0,AT,$hi0
+ stq $lo0,0($rp)
+ cmpult $tp,$tj,v0
+ lda $rp,8($rp)
+ bne v0,.Lsub
+
+ subq $hi1,$hi0,$hi0 # handle upmost overflow bit
+ mov sp,$tp
+ mov $bp,$rp # restore rp
+
+.align 4
+.Lcopy: ldq $aj,0($tp) # conditional copy
+ ldq $nj,0($rp)
+ lda $tp,8($tp)
+ lda $rp,8($rp)
+ cmoveq $hi0,$nj,$aj
+ stq zero,-8($tp) # zap tp
+ cmpult $tp,$tj,AT
+ stq $aj,-8($rp)
+ bne AT,.Lcopy
+ mov 1,v0
+
+.Lexit:
+ .set noreorder
+ mov fp,sp
+ /*ldq ra,0(sp)*/
+ ldq s3,8(sp)
+ ldq s4,16(sp)
+ ldq s5,24(sp)
+ ldq fp,32(sp)
+ lda sp,48(sp)
+ ret (ra)
+.end bn_mul_mont
+.ascii "Montgomery Multiplication for Alpha, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+___
+
+print $code;
+close STDOUT or die "error closing STDOUT: $!";
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..3192eab3092a 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-2025 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with 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,36 @@ $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__
+#ifndef __AARCH64EB__
+ adrp x17,OPENSSL_armv8_rsa_neonized
+ ldr w17,[x17,#:lo12:OPENSSL_armv8_rsa_neonized]
+ cbnz w17, bn_mul8x_mont_neon
+#endif
+#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 +220,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 +276,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 +294,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 +982,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 +1180,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 +1238,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..4ffe443066cc 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.
+ * 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
@@ -381,25 +381,33 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
#ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
t1 = a[0];
- t2 = b[0];
- r[0] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[0];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[0] = t1;
+ c += (t1 > t2);
t1 = a[1];
- t2 = b[1];
- r[1] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[1];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[1] = t1;
+ c += (t1 > t2);
t1 = a[2];
- t2 = b[2];
- r[2] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[2];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[2] = t1;
+ c += (t1 > t2);
t1 = a[3];
- t2 = b[3];
- r[3] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[3];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[3] = t1;
+ c += (t1 > t2);
a += 4;
b += 4;
r += 4;
@@ -408,10 +416,12 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
#endif
while (n) {
t1 = a[0];
- t2 = b[0];
- r[0] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[0];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[0] = t1;
+ c += (t1 > t2);
a++;
b++;
r++;
@@ -446,7 +456,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
@@ -455,11 +465,11 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
BN_ULLONG tt = t+c0; /* no carry */ \
c0 = (BN_ULONG)Lw(tt); \
hi = (BN_ULONG)Hw(tt); \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
@@ -468,7 +478,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
@@ -483,26 +493,26 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo, hi; \
BN_UMULT_LOHI(lo,hi,ta,tb); \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo, hi, tt; \
BN_UMULT_LOHI(lo,hi,ta,tb); \
- c0 += lo; tt = hi+((c0<lo)?1:0); \
- c1 += tt; c2 += (c1<tt)?1:0; \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; tt = hi + (c0<lo); \
+ c1 += tt; c2 += (c1<tt); \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG ta = (a)[i]; \
BN_ULONG lo, hi; \
BN_UMULT_LOHI(lo,hi,ta,ta); \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
@@ -517,26 +527,26 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo = ta * tb; \
BN_ULONG hi = BN_UMULT_HIGH(ta,tb); \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
BN_ULONG ta = (a), tb = (b), tt; \
BN_ULONG lo = ta * tb; \
BN_ULONG hi = BN_UMULT_HIGH(ta,tb); \
- c0 += lo; tt = hi + ((c0<lo)?1:0); \
- c1 += tt; c2 += (c1<tt)?1:0; \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; tt = hi + (c0<lo); \
+ c1 += tt; c2 += (c1<tt); \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG ta = (a)[i]; \
BN_ULONG lo = ta * ta; \
BN_ULONG hi = BN_UMULT_HIGH(ta,ta); \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
@@ -551,8 +561,8 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
mul64(lo,hi,bl,bh); \
- c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c0 = (c0+lo)&BN_MASK2; hi += (c0<lo); \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
@@ -561,17 +571,17 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
mul64(lo,hi,bl,bh); \
tt = hi; \
- c0 = (c0+lo)&BN_MASK2; if (c0<lo) tt++; \
- c1 = (c1+tt)&BN_MASK2; if (c1<tt) c2++; \
- c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c0 = (c0+lo)&BN_MASK2; tt += (c0<lo); \
+ c1 = (c1+tt)&BN_MASK2; c2 += (c1<tt); \
+ c0 = (c0+lo)&BN_MASK2; hi += (c0<lo); \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG lo, hi; \
sqr64(lo,hi,(a)[i]); \
- c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c0 = (c0+lo)&BN_MASK2; hi += (c0<lo); \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c
index dd5beea7c93e..7e5a1c52e27d 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
@@ -13,6 +13,20 @@
#define BN_BLINDING_COUNTER 32
+struct bn_blinding_st {
+ BIGNUM *A;
+ BIGNUM *Ai;
+ BIGNUM *e;
+ BIGNUM *mod; /* just a reference */
+ CRYPTO_THREAD_ID tid;
+ int counter;
+ unsigned long flags;
+ BN_MONT_CTX *m_ctx;
+ int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+ CRYPTO_RWLOCK *lock;
+};
+
BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
{
BN_BLINDING *ret = NULL;
@@ -20,13 +34,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 +95,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 +138,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 +172,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;
}
@@ -177,7 +191,8 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
n->top = (int)(rtop & ~mask) | (ntop & mask);
n->flags |= (BN_FLG_FIXED_TOP & ~mask);
}
- ret = BN_mod_mul_montgomery(n, n, r, b->m_ctx, ctx);
+ ret = bn_mul_mont_fixed_top(n, n, r, b->m_ctx, ctx);
+ bn_correct_top_consttime(n);
} else {
ret = BN_mod_mul(n, n, r, b->mod, ctx);
}
@@ -256,7 +271,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 +283,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..0e563ad823c7 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.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
}
@@ -244,6 +243,14 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
wstart = bits - 1; /* The top bit of the window */
wend = 0; /* The bottom bit of the window */
+ if (r == p) {
+ BIGNUM *p_dup = BN_CTX_get(ctx);
+
+ if (p_dup == NULL || BN_copy(p_dup, p) == NULL)
+ goto err;
+ p = p_dup;
+ }
+
if (!BN_one(r))
goto err;
@@ -262,7 +269,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 +325,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 +427,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++) {
@@ -601,7 +606,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
* out by Colin Percival,
* http://www.daemonology.net/hyperthreading-considered-harmful/)
*/
-int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *in_mont)
{
@@ -618,12 +623,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
unsigned int t4 = 0;
#endif
- bn_check_top(a);
- bn_check_top(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 +842,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 +951,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;
@@ -1141,7 +1142,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
goto err;
} else
#endif
- if (!BN_from_montgomery(rr, &tmp, mont, ctx))
+ if (!bn_from_mont_fixed_top(rr, &tmp, mont, ctx))
goto err;
ret = 1;
err:
@@ -1155,6 +1156,19 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
return ret;
}
+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)
+{
+ bn_check_top(a);
+ bn_check_top(p);
+ bn_check_top(m);
+ if (!bn_mod_exp_mont_fixed_top(rr, a, p, m, ctx, in_mont))
+ return 0;
+ bn_correct_top(rr);
+ return 1;
+}
+
int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
{
@@ -1184,7 +1198,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 +1206,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 +1330,12 @@ 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;
+ }
+
+ if (r == m) {
+ ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
@@ -1365,6 +1384,14 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
wstart = bits - 1; /* The top bit of the window */
wend = 0; /* The bottom bit of the window */
+ if (r == p) {
+ BIGNUM *p_dup = BN_CTX_get(ctx);
+
+ if (p_dup == NULL || BN_copy(p_dup, p) == NULL)
+ goto err;
+ p = p_dup;
+ }
+
if (!BN_one(r))
goto err;
@@ -1383,7 +1410,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 +1448,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..cd0b0151ec7e 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.
+ * 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
@@ -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;
}
@@ -611,9 +611,9 @@ int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
for (i = 0; i < m; i++) {
/* conditionally flip signs if delta is positive and g is odd */
- cond = (-delta >> (8 * sizeof(delta) - 1)) & g->d[0] & 1
+ cond = ((unsigned int)-delta >> (8 * sizeof(delta) - 1)) & g->d[0] & 1
/* make sure g->top > 0 (i.e. if top == 0 then g == 0 always) */
- & (~((g->top - 1) >> (sizeof(g->top) * 8 - 1)));
+ & (~((unsigned int)(g->top - 1) >> (sizeof(g->top) * 8 - 1)));
delta = (-cond & -delta) | ((cond - 1) & delta);
r->neg ^= cond;
/* swap */
@@ -625,7 +625,7 @@ int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
goto err;
BN_consttime_swap(g->d[0] & 1 /* g is odd */
/* make sure g->top > 0 (i.e. if top == 0 then g == 0 always) */
- & (~((g->top - 1) >> (sizeof(g->top) * 8 - 1))),
+ & (~((unsigned int)(g->top - 1) >> (sizeof(g->top) * 8 - 1))),
g, temp, top);
if (!BN_rshift1(g, g))
goto err;
diff --git a/crypto/bn/bn_gf2m.c b/crypto/bn/bn_gf2m.c
index a2ea86755182..bcc66613cc14 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
@@ -15,6 +15,7 @@
#include "bn_local.h"
#ifndef OPENSSL_NO_EC2M
+# include <openssl/ec.h>
/*
* Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should
@@ -297,7 +298,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 +396,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 +468,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 +531,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 +716,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);
@@ -725,15 +735,21 @@ int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *b = NULL;
int ret = 0;
+ int numbits;
BN_CTX_start(ctx);
if ((b = BN_CTX_get(ctx)) == NULL)
goto err;
+ /* Fail on a non-sensical input p value */
+ numbits = BN_num_bits(p);
+ if (numbits <= 1)
+ goto err;
+
/* 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, numbits - 1,
+ BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx))
goto err;
} while (BN_is_zero(b));
@@ -899,15 +915,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 +950,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 +980,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 +1014,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 +1057,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 +1080,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 +1090,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 +1116,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);
@@ -1109,16 +1141,26 @@ int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
/*
* Convert the bit-string representation of a polynomial ( \sum_{i=0}^n a_i *
* x^i) into an array of integers corresponding to the bits with non-zero
- * coefficient. Array is terminated with -1. Up to max elements of the array
- * will be filled. Return value is total number of array elements that would
- * be filled if array was large enough.
+ * coefficient. The array is intended to be suitable for use with
+ * `BN_GF2m_mod_arr()`, and so the constant term of the polynomial must not be
+ * zero. This translates to a requirement that the input BIGNUM `a` is odd.
+ *
+ * Given sufficient room, the array is terminated with -1. Up to max elements
+ * of the array will be filled.
+ *
+ * The return value is total number of array elements that would be filled if
+ * array was large enough, including the terminating `-1`. It is `0` when `a`
+ * is not odd or the constant term is zero contrary to requirement.
+ *
+ * The return value is also `0` when the leading exponent exceeds
+ * `OPENSSL_ECC_MAX_FIELD_BITS`, this guards against CPU exhaustion attacks,
*/
int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
{
int i, j, k = 0;
BN_ULONG mask;
- if (BN_is_zero(a))
+ if (!BN_is_odd(a))
return 0;
for (i = a->top - 1; i >= 0; i--) {
@@ -1136,12 +1178,13 @@ int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
}
}
- if (k < max) {
+ if (k > 0 && p[0] > OPENSSL_ECC_MAX_FIELD_BITS)
+ return 0;
+
+ if (k < max)
p[k] = -1;
- k++;
- }
- return k;
+ return k + 1;
}
/*
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..9677a603cb2d 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,19 +595,52 @@ 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;
BN_ULONG t1, t2, *ap, *bp;
+ ap = a->d;
+ bp = b->d;
+
+ if (BN_get_flags(a, BN_FLG_CONSTTIME)
+ && a->top == b->top) {
+ int res = 0;
+
+ for (i = 0; i < b->top; i++) {
+ res = constant_time_select_int(constant_time_lt_bn(ap[i], bp[i]),
+ -1, res);
+ res = constant_time_select_int(constant_time_lt_bn(bp[i], ap[i]),
+ 1, res);
+ }
+ return res;
+ }
+
bn_check_top(a);
bn_check_top(b);
i = a->top - b->top;
if (i != 0)
return i;
- ap = a->d;
- bp = b->d;
+
for (i = a->top - 1; i >= 0; i--) {
t1 = ap[i];
t2 = bp[i];
@@ -717,11 +752,10 @@ int BN_is_bit_set(const BIGNUM *a, int n)
return (int)(((a->d[i]) >> j) & ((BN_ULONG)1));
}
-int BN_mask_bits(BIGNUM *a, int n)
+int ossl_bn_mask_bits_fixed_top(BIGNUM *a, int n)
{
int b, w;
- bn_check_top(a);
if (n < 0)
return 0;
@@ -735,10 +769,21 @@ int BN_mask_bits(BIGNUM *a, int n)
a->top = w + 1;
a->d[w] &= ~(BN_MASK2 << b);
}
- bn_correct_top(a);
+ a->flags |= BN_FLG_FIXED_TOP;
return 1;
}
+int BN_mask_bits(BIGNUM *a, int n)
+{
+ int ret;
+
+ bn_check_top(a);
+ ret = ossl_bn_mask_bits_fixed_top(a, n);
+ if (ret)
+ bn_correct_top(a);
+ return ret;
+}
+
void BN_set_negative(BIGNUM *a, int b)
{
if (b && !BN_is_zero(a))
@@ -915,6 +960,22 @@ int BN_is_word(const BIGNUM *a, const BN_ULONG w)
return BN_abs_is_word(a, w) && (!w || !a->neg);
}
+int ossl_bn_is_word_fixed_top(const BIGNUM *a, BN_ULONG w)
+{
+ int res, i;
+ const BN_ULONG *ap = a->d;
+
+ if (a->neg || a->top == 0)
+ return 0;
+
+ res = constant_time_select_int(constant_time_eq_bn(ap[0], w), 1, 0);
+
+ for (i = 1; i < a->top; i++)
+ res = constant_time_select_int(constant_time_is_zero_bn(ap[i]),
+ res, 0);
+ return res;
+}
+
int BN_is_odd(const BIGNUM *a)
{
return (a->top > 0) && (a->d[0] & 1);
@@ -947,7 +1008,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;
}
@@ -1001,6 +1062,28 @@ BIGNUM *bn_wexpand(BIGNUM *a, int words)
return (words <= a->dmax) ? a : bn_expand2(a, words);
}
+void bn_correct_top_consttime(BIGNUM *a)
+{
+ int j, atop;
+ BN_ULONG limb;
+ unsigned int mask;
+
+ for (j = 0, atop = 0; j < a->dmax; j++) {
+ limb = a->d[j];
+ limb |= 0 - limb;
+ limb >>= BN_BITS2 - 1;
+ limb = 0 - limb;
+ mask = (unsigned int)limb;
+ mask &= constant_time_msb(j - a->top);
+ atop = constant_time_select_int(mask, j + 1, atop);
+ }
+
+ mask = constant_time_eq_int(atop, 0);
+ a->top = atop;
+ a->neg = constant_time_select_int(mask, 0, a->neg);
+ a->flags &= ~BN_FLG_FIXED_TOP;
+}
+
void bn_correct_top(BIGNUM *a)
{
BN_ULONG *ftl;
diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h
index 30b7614fdbb2..50e9d26e215b 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)); \
} \
@@ -283,20 +290,6 @@ struct bn_gencb_st {
} cb;
};
-struct bn_blinding_st {
- BIGNUM *A;
- BIGNUM *Ai;
- BIGNUM *e;
- BIGNUM *mod; /* just a reference */
- CRYPTO_THREAD_ID tid;
- int counter;
- unsigned long flags;
- BN_MONT_CTX *m_ctx;
- int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
- CRYPTO_RWLOCK *lock;
-};
-
/*-
* BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
*
@@ -371,24 +364,6 @@ struct bn_blinding_st {
# define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32)/* 32 */
# define BN_MONT_CTX_SET_SIZE_WORD (64)/* 32 */
-/*
- * 2011-02-22 SMS. In various places, a size_t variable or a type cast to
- * size_t was used to perform integer-only operations on pointers. This
- * failed on VMS with 64-bit pointers (CC /POINTER_SIZE = 64) because size_t
- * is still only 32 bits. What's needed in these cases is an integer type
- * with the same size as a pointer, which size_t is not certain to be. The
- * only fix here is VMS-specific.
- */
-# if defined(OPENSSL_SYS_VMS)
-# if __INITIAL_POINTER_SIZE == 64
-# define PTR_SIZE_INT long long
-# else /* __INITIAL_POINTER_SIZE == 64 */
-# define PTR_SIZE_INT int
-# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
-# elif !defined(PTR_SIZE_INT) /* defined(OPENSSL_SYS_VMS) */
-# define PTR_SIZE_INT size_t
-# endif /* defined(OPENSSL_SYS_VMS) [else] */
-
# if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC)
/*
* BN_UMULT_HIGH section.
@@ -408,9 +383,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 +458,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; \
@@ -529,10 +504,10 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
ret = (r); \
BN_UMULT_LOHI(low,high,w,tmp); \
ret += (c); \
- (c) = (ret<(c))?1:0; \
+ (c) = (ret<(c)); \
(c) += high; \
ret += low; \
- (c) += (ret<low)?1:0; \
+ (c) += (ret<low); \
(r) = ret; \
}
@@ -541,7 +516,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
BN_UMULT_LOHI(low,high,w,ta); \
ret = low + (c); \
(c) = high; \
- (c) += (ret<low)?1:0; \
+ (c) += (ret<low); \
(r) = ret; \
}
@@ -557,10 +532,10 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
high= BN_UMULT_HIGH(w,tmp); \
ret += (c); \
low = (w) * tmp; \
- (c) = (ret<(c))?1:0; \
+ (c) = (ret<(c)); \
(c) += high; \
ret += low; \
- (c) += (ret<low)?1:0; \
+ (c) += (ret<low); \
(r) = ret; \
}
@@ -570,7 +545,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
high= BN_UMULT_HIGH(w,ta); \
ret = low + (c); \
(c) = high; \
- (c) += (ret<low)?1:0; \
+ (c) += (ret<low); \
(r) = ret; \
}
@@ -603,10 +578,10 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
lt=(bl)*(lt); \
m1=(bl)*(ht); \
ht =(bh)*(ht); \
- m=(m+m1)&BN_MASK2; if (m < m1) ht+=L2HBITS((BN_ULONG)1); \
+ m=(m+m1)&BN_MASK2; ht += L2HBITS((BN_ULONG)(m < m1)); \
ht+=HBITS(m); \
m1=L2HBITS(m); \
- lt=(lt+m1)&BN_MASK2; if (lt < m1) ht++; \
+ lt=(lt+m1)&BN_MASK2; ht += (lt < m1); \
(l)=lt; \
(h)=ht; \
}
@@ -623,7 +598,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
h*=h; \
h+=(m&BN_MASK2h1)>>(BN_BITS4-1); \
m =(m&BN_MASK2l)<<(BN_BITS4+1); \
- l=(l+m)&BN_MASK2; if (l < m) h++; \
+ l=(l+m)&BN_MASK2; h += (l < m); \
(lo)=l; \
(ho)=h; \
}
@@ -637,9 +612,9 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
mul64(l,h,(bl),(bh)); \
\
/* non-multiply part */ \
- l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
+ l=(l+(c))&BN_MASK2; h += (l < (c)); \
(c)=(r); \
- l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
+ l=(l+(c))&BN_MASK2; h += (l < (c)); \
(c)=h&BN_MASK2; \
(r)=l; \
}
@@ -653,7 +628,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
mul64(l,h,(bl),(bh)); \
\
/* non-multiply part */ \
- l+=(c); if ((l&BN_MASK2) < (c)) h++; \
+ l+=(c); h += ((l&BN_MASK2) < (c)); \
(c)=h&BN_MASK2; \
(r)=l&BN_MASK2; \
}
@@ -683,7 +658,7 @@ BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int cl, int dl);
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);
-
+void bn_correct_top_consttime(BIGNUM *a);
BIGNUM *int_bn_mod_inverse(BIGNUM *in,
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx,
int *noinv);
@@ -699,4 +674,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..2dda2e3442ed 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
@@ -17,6 +17,11 @@ int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
* always holds)
*/
+ if (r == d) {
+ ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
if (!(BN_mod(r, m, d, ctx)))
return 0;
if (!r->neg)
@@ -56,9 +61,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;
@@ -182,6 +191,11 @@ int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m)
{
+ if (r == m) {
+ ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
if (!BN_sub(r, a, b))
return 0;
if (r->neg)
@@ -291,7 +305,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..d761e5702da2 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.
+ * Copyright 2002-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
@@ -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;
}
/*
@@ -319,6 +319,28 @@ static void nist_cp_bn(BN_ULONG *dst, const BN_ULONG *src, int top)
# endif
#endif /* BN_BITS2 != 64 */
+#ifdef NIST_INT64
+/* Helpers to load/store a 32-bit word (uint32_t) from/into a memory
+ * location and avoid potential aliasing issue. */
+static ossl_inline uint32_t load_u32(const void *ptr)
+{
+ uint32_t tmp;
+
+ memcpy(&tmp, ptr, sizeof(tmp));
+ return tmp;
+}
+
+static ossl_inline void store_lo32(void *ptr, NIST_INT64 val)
+{
+ /* A cast is needed for big-endian system: on a 32-bit BE system
+ * NIST_INT64 may be defined as well if the compiler supports 64-bit
+ * long long. */
+ uint32_t tmp = (uint32_t)val;
+
+ memcpy(ptr, &tmp, sizeof(tmp));
+}
+#endif /* NIST_INT64 */
+
#define nist_set_192(to, from, a1, a2, a3) \
{ \
bn_cp_64(to, 0, from, (a3) - 3) \
@@ -338,17 +360,16 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
sizeof(unsigned int)];
} 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);
@@ -375,42 +396,42 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
unsigned int *rp = (unsigned int *)r_d;
const unsigned int *bp = (const unsigned int *)buf.ui;
- acc = rp[0];
+ acc = load_u32(&rp[0]);
acc += bp[3 * 2 - 6];
acc += bp[5 * 2 - 6];
- rp[0] = (unsigned int)acc;
+ store_lo32(&rp[0], acc);
acc >>= 32;
- acc += rp[1];
+ acc += load_u32(&rp[1]);
acc += bp[3 * 2 - 5];
acc += bp[5 * 2 - 5];
- rp[1] = (unsigned int)acc;
+ store_lo32(&rp[1], acc);
acc >>= 32;
- acc += rp[2];
+ acc += load_u32(&rp[2]);
acc += bp[3 * 2 - 6];
acc += bp[4 * 2 - 6];
acc += bp[5 * 2 - 6];
- rp[2] = (unsigned int)acc;
+ store_lo32(&rp[2], acc);
acc >>= 32;
- acc += rp[3];
+ acc += load_u32(&rp[3]);
acc += bp[3 * 2 - 5];
acc += bp[4 * 2 - 5];
acc += bp[5 * 2 - 5];
- rp[3] = (unsigned int)acc;
+ store_lo32(&rp[3], acc);
acc >>= 32;
- acc += rp[4];
+ acc += load_u32(&rp[4]);
acc += bp[4 * 2 - 6];
acc += bp[5 * 2 - 6];
- rp[4] = (unsigned int)acc;
+ store_lo32(&rp[4], acc);
acc >>= 32;
- acc += rp[5];
+ acc += load_u32(&rp[5]);
acc += bp[4 * 2 - 5];
acc += bp[5 * 2 - 5];
- rp[5] = (unsigned int)acc;
+ store_lo32(&rp[5], acc);
carry = (int)(acc >> 32);
}
@@ -439,13 +460,9 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
* 'tmp=result-modulus; if (!carry || !borrow) result=tmp;'
* this is what happens below, but without explicit if:-) a.
*/
- mask =
- 0 - (PTR_SIZE_INT) bn_sub_words(c_d, r_d, _nist_p_192[0],
- BN_NIST_192_TOP);
- mask &= 0 - (PTR_SIZE_INT) carry;
- res = c_d;
- res = (BN_ULONG *)
- (((PTR_SIZE_INT) res & ~mask) | ((PTR_SIZE_INT) r_d & mask));
+ res = (bn_sub_words(c_d, r_d, _nist_p_192[0], BN_NIST_192_TOP) && carry)
+ ? r_d
+ : c_d;
nist_cp_bn(r_d, res, BN_NIST_192_TOP);
r->top = BN_NIST_192_TOP;
bn_correct_top(r);
@@ -479,21 +496,17 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
sizeof(unsigned int)];
} buf;
BN_ULONG c_d[BN_NIST_224_TOP], *res;
- PTR_SIZE_INT mask;
- union {
- bn_addsub_f f;
- PTR_SIZE_INT p;
- } u;
- static const BIGNUM _bignum_nist_p_224_sqr = {
+ bn_addsub_f adjust;
+ 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);
@@ -597,7 +610,7 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
# endif
}
#endif
- u.f = bn_sub_words;
+ adjust = bn_sub_words;
if (carry > 0) {
carry =
(int)bn_sub_words(r_d, r_d, _nist_p_224[carry - 1],
@@ -616,19 +629,14 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
carry =
(int)bn_add_words(r_d, r_d, _nist_p_224[-carry - 1],
BN_NIST_224_TOP);
- mask = 0 - (PTR_SIZE_INT) carry;
- u.p = ((PTR_SIZE_INT) bn_sub_words & mask) |
- ((PTR_SIZE_INT) bn_add_words & ~mask);
+ adjust = carry ? bn_sub_words : bn_add_words;
} else
carry = 1;
/* otherwise it's effectively same as in BN_nist_mod_192... */
- mask =
- 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_224[0], BN_NIST_224_TOP);
- mask &= 0 - (PTR_SIZE_INT) carry;
- res = c_d;
- res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) |
- ((PTR_SIZE_INT) r_d & mask));
+ res = ((*adjust) (c_d, r_d, _nist_p_224[0], BN_NIST_224_TOP) && carry)
+ ? r_d
+ : c_d;
nist_cp_bn(r_d, res, BN_NIST_224_TOP);
r->top = BN_NIST_224_TOP;
bn_correct_top(r);
@@ -660,21 +668,17 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
sizeof(unsigned int)];
} buf;
BN_ULONG c_d[BN_NIST_256_TOP], *res;
- PTR_SIZE_INT mask;
- union {
- bn_addsub_f f;
- PTR_SIZE_INT p;
- } u;
- static const BIGNUM _bignum_nist_p_256_sqr = {
+ bn_addsub_f adjust;
+ 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);
@@ -701,36 +705,36 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
unsigned int *rp = (unsigned int *)r_d;
const unsigned int *bp = (const unsigned int *)buf.ui;
- acc = rp[0];
+ acc = load_u32(&rp[0]);
acc += bp[8 - 8];
acc += bp[9 - 8];
acc -= bp[11 - 8];
acc -= bp[12 - 8];
acc -= bp[13 - 8];
acc -= bp[14 - 8];
- rp[0] = (unsigned int)acc;
+ store_lo32(&rp[0], acc);
acc >>= 32;
- acc += rp[1];
+ acc += load_u32(&rp[1]);
acc += bp[9 - 8];
acc += bp[10 - 8];
acc -= bp[12 - 8];
acc -= bp[13 - 8];
acc -= bp[14 - 8];
acc -= bp[15 - 8];
- rp[1] = (unsigned int)acc;
+ store_lo32(&rp[1], acc);
acc >>= 32;
- acc += rp[2];
+ acc += load_u32(&rp[2]);
acc += bp[10 - 8];
acc += bp[11 - 8];
acc -= bp[13 - 8];
acc -= bp[14 - 8];
acc -= bp[15 - 8];
- rp[2] = (unsigned int)acc;
+ store_lo32(&rp[2], acc);
acc >>= 32;
- acc += rp[3];
+ acc += load_u32(&rp[3]);
acc += bp[11 - 8];
acc += bp[11 - 8];
acc += bp[12 - 8];
@@ -739,10 +743,10 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc -= bp[15 - 8];
acc -= bp[8 - 8];
acc -= bp[9 - 8];
- rp[3] = (unsigned int)acc;
+ store_lo32(&rp[3], acc);
acc >>= 32;
- acc += rp[4];
+ acc += load_u32(&rp[4]);
acc += bp[12 - 8];
acc += bp[12 - 8];
acc += bp[13 - 8];
@@ -750,10 +754,10 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc += bp[14 - 8];
acc -= bp[9 - 8];
acc -= bp[10 - 8];
- rp[4] = (unsigned int)acc;
+ store_lo32(&rp[4], acc);
acc >>= 32;
- acc += rp[5];
+ acc += load_u32(&rp[5]);
acc += bp[13 - 8];
acc += bp[13 - 8];
acc += bp[14 - 8];
@@ -761,10 +765,10 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc += bp[15 - 8];
acc -= bp[10 - 8];
acc -= bp[11 - 8];
- rp[5] = (unsigned int)acc;
+ store_lo32(&rp[5], acc);
acc >>= 32;
- acc += rp[6];
+ acc += load_u32(&rp[6]);
acc += bp[14 - 8];
acc += bp[14 - 8];
acc += bp[15 - 8];
@@ -773,10 +777,10 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc += bp[13 - 8];
acc -= bp[8 - 8];
acc -= bp[9 - 8];
- rp[6] = (unsigned int)acc;
+ store_lo32(&rp[6], acc);
acc >>= 32;
- acc += rp[7];
+ acc += load_u32(&rp[7]);
acc += bp[15 - 8];
acc += bp[15 - 8];
acc += bp[15 - 8];
@@ -785,7 +789,7 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc -= bp[11 - 8];
acc -= bp[12 - 8];
acc -= bp[13 - 8];
- rp[7] = (unsigned int)acc;
+ store_lo32(&rp[7], acc);
carry = (int)(acc >> 32);
}
@@ -850,7 +854,7 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
}
#endif
/* see BN_nist_mod_224 for explanation */
- u.f = bn_sub_words;
+ adjust = bn_sub_words;
if (carry > 0)
carry =
(int)bn_sub_words(r_d, r_d, _nist_p_256[carry - 1],
@@ -859,18 +863,13 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
carry =
(int)bn_add_words(r_d, r_d, _nist_p_256[-carry - 1],
BN_NIST_256_TOP);
- mask = 0 - (PTR_SIZE_INT) carry;
- u.p = ((PTR_SIZE_INT) bn_sub_words & mask) |
- ((PTR_SIZE_INT) bn_add_words & ~mask);
+ adjust = carry ? bn_sub_words : bn_add_words;
} else
carry = 1;
- mask =
- 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_256[0], BN_NIST_256_TOP);
- mask &= 0 - (PTR_SIZE_INT) carry;
- res = c_d;
- res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) |
- ((PTR_SIZE_INT) r_d & mask));
+ res = ((*adjust) (c_d, r_d, _nist_p_256[0], BN_NIST_256_TOP) && carry)
+ ? r_d
+ : c_d;
nist_cp_bn(r_d, res, BN_NIST_256_TOP);
r->top = BN_NIST_256_TOP;
bn_correct_top(r);
@@ -906,21 +905,17 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
sizeof(unsigned int)];
} buf;
BN_ULONG c_d[BN_NIST_384_TOP], *res;
- PTR_SIZE_INT mask;
- union {
- bn_addsub_f f;
- PTR_SIZE_INT p;
- } u;
- static const BIGNUM _bignum_nist_p_384_sqr = {
+ bn_addsub_f adjust;
+ 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);
@@ -947,32 +942,32 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
unsigned int *rp = (unsigned int *)r_d;
const unsigned int *bp = (const unsigned int *)buf.ui;
- acc = rp[0];
+ acc = load_u32(&rp[0]);
acc += bp[12 - 12];
acc += bp[21 - 12];
acc += bp[20 - 12];
acc -= bp[23 - 12];
- rp[0] = (unsigned int)acc;
+ store_lo32(&rp[0], acc);
acc >>= 32;
- acc += rp[1];
+ acc += load_u32(&rp[1]);
acc += bp[13 - 12];
acc += bp[22 - 12];
acc += bp[23 - 12];
acc -= bp[12 - 12];
acc -= bp[20 - 12];
- rp[1] = (unsigned int)acc;
+ store_lo32(&rp[1], acc);
acc >>= 32;
- acc += rp[2];
+ acc += load_u32(&rp[2]);
acc += bp[14 - 12];
acc += bp[23 - 12];
acc -= bp[13 - 12];
acc -= bp[21 - 12];
- rp[2] = (unsigned int)acc;
+ store_lo32(&rp[2], acc);
acc >>= 32;
- acc += rp[3];
+ acc += load_u32(&rp[3]);
acc += bp[15 - 12];
acc += bp[12 - 12];
acc += bp[20 - 12];
@@ -980,10 +975,10 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc -= bp[14 - 12];
acc -= bp[22 - 12];
acc -= bp[23 - 12];
- rp[3] = (unsigned int)acc;
+ store_lo32(&rp[3], acc);
acc >>= 32;
- acc += rp[4];
+ acc += load_u32(&rp[4]);
acc += bp[21 - 12];
acc += bp[21 - 12];
acc += bp[16 - 12];
@@ -994,10 +989,10 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc -= bp[15 - 12];
acc -= bp[23 - 12];
acc -= bp[23 - 12];
- rp[4] = (unsigned int)acc;
+ store_lo32(&rp[4], acc);
acc >>= 32;
- acc += rp[5];
+ acc += load_u32(&rp[5]);
acc += bp[22 - 12];
acc += bp[22 - 12];
acc += bp[17 - 12];
@@ -1006,10 +1001,10 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc += bp[21 - 12];
acc += bp[23 - 12];
acc -= bp[16 - 12];
- rp[5] = (unsigned int)acc;
+ store_lo32(&rp[5], acc);
acc >>= 32;
- acc += rp[6];
+ acc += load_u32(&rp[6]);
acc += bp[23 - 12];
acc += bp[23 - 12];
acc += bp[18 - 12];
@@ -1017,48 +1012,48 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
acc += bp[14 - 12];
acc += bp[22 - 12];
acc -= bp[17 - 12];
- rp[6] = (unsigned int)acc;
+ store_lo32(&rp[6], acc);
acc >>= 32;
- acc += rp[7];
+ acc += load_u32(&rp[7]);
acc += bp[19 - 12];
acc += bp[16 - 12];
acc += bp[15 - 12];
acc += bp[23 - 12];
acc -= bp[18 - 12];
- rp[7] = (unsigned int)acc;
+ store_lo32(&rp[7], acc);
acc >>= 32;
- acc += rp[8];
+ acc += load_u32(&rp[8]);
acc += bp[20 - 12];
acc += bp[17 - 12];
acc += bp[16 - 12];
acc -= bp[19 - 12];
- rp[8] = (unsigned int)acc;
+ store_lo32(&rp[8], acc);
acc >>= 32;
- acc += rp[9];
+ acc += load_u32(&rp[9]);
acc += bp[21 - 12];
acc += bp[18 - 12];
acc += bp[17 - 12];
acc -= bp[20 - 12];
- rp[9] = (unsigned int)acc;
+ store_lo32(&rp[9], acc);
acc >>= 32;
- acc += rp[10];
+ acc += load_u32(&rp[10]);
acc += bp[22 - 12];
acc += bp[19 - 12];
acc += bp[18 - 12];
acc -= bp[21 - 12];
- rp[10] = (unsigned int)acc;
+ store_lo32(&rp[10], acc);
acc >>= 32;
- acc += rp[11];
+ acc += load_u32(&rp[11]);
acc += bp[23 - 12];
acc += bp[20 - 12];
acc += bp[19 - 12];
acc -= bp[22 - 12];
- rp[11] = (unsigned int)acc;
+ store_lo32(&rp[11], acc);
carry = (int)(acc >> 32);
}
@@ -1131,7 +1126,7 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
}
#endif
/* see BN_nist_mod_224 for explanation */
- u.f = bn_sub_words;
+ adjust = bn_sub_words;
if (carry > 0)
carry =
(int)bn_sub_words(r_d, r_d, _nist_p_384[carry - 1],
@@ -1140,18 +1135,13 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
carry =
(int)bn_add_words(r_d, r_d, _nist_p_384[-carry - 1],
BN_NIST_384_TOP);
- mask = 0 - (PTR_SIZE_INT) carry;
- u.p = ((PTR_SIZE_INT) bn_sub_words & mask) |
- ((PTR_SIZE_INT) bn_add_words & ~mask);
+ adjust = carry ? bn_sub_words : bn_add_words;
} else
carry = 1;
- mask =
- 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_384[0], BN_NIST_384_TOP);
- mask &= 0 - (PTR_SIZE_INT) carry;
- res = c_d;
- res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) |
- ((PTR_SIZE_INT) r_d & mask));
+ res = ((*adjust) (c_d, r_d, _nist_p_384[0], BN_NIST_384_TOP) && carry)
+ ? r_d
+ : c_d;
nist_cp_bn(r_d, res, BN_NIST_384_TOP);
r->top = BN_NIST_384_TOP;
bn_correct_top(r);
@@ -1168,17 +1158,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);
@@ -1221,12 +1210,10 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
r_d[i] &= BN_NIST_521_TOP_MASK;
bn_add_words(r_d, r_d, t_d, BN_NIST_521_TOP);
- mask =
- 0 - (PTR_SIZE_INT) bn_sub_words(t_d, r_d, _nist_p_521,
- BN_NIST_521_TOP);
- res = t_d;
- res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) |
- ((PTR_SIZE_INT) r_d & mask));
+ res = bn_sub_words(t_d, r_d, _nist_p_521,
+ BN_NIST_521_TOP)
+ ? r_d
+ : t_d;
nist_cp_bn(r_d, res, BN_NIST_521_TOP);
r->top = BN_NIST_521_TOP;
bn_correct_top(r);
@@ -1236,15 +1223,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..ba0970b1f87d 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,
+ strength, 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,20 +237,68 @@ int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
{
return BN_rand_range(r, range);
}
+# endif
+#endif
+
+int ossl_bn_priv_rand_range_fixed_top(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)) {
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_RANGE);
+ return 0;
+ }
+
+ n = BN_num_bits(range); /* n > 0 */
+
+ /* BN_is_bit_set(range, n - 1) always holds */
+
+ if (n == 1) {
+ BN_zero(r);
+ } else {
+ BN_set_flags(r, BN_FLG_CONSTTIME);
+ do {
+ if (!bnrand(PRIVATE, r, n + 1, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY,
+ strength, ctx))
+ return 0;
+
+ if (!--count) {
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
+ return 0;
+ }
+ ossl_bn_mask_bits_fixed_top(r, n);
+ }
+ while (BN_ucmp(r, range) >= 0);
+#ifdef BN_DEBUG
+ /* With BN_DEBUG on a fixed top number cannot be returned */
+ bn_correct_top(r);
+#endif
+ }
+
+ return 1;
+}
/*
- * BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike
- * BN_rand_range, it also includes the contents of |priv| and |message| in
- * the generation so that an RNG failure isn't fatal as long as |priv|
+ * ossl_bn_gen_dsa_nonce_fixed_top generates a random number 0 <= out < range.
+ * Unlike BN_rand_range, it also includes the contents of |priv| and |message|
+ * in the generation so that an RNG failure isn't fatal as long as |priv|
* remains secret. This is intended for use in DSA and ECDSA where an RNG
* weakness leads directly to private key exposure unless this function is
* used.
*/
-int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
- const BIGNUM *priv, const unsigned char *message,
- size_t message_len, BN_CTX *ctx)
+int ossl_bn_gen_dsa_nonce_fixed_top(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.
@@ -214,15 +306,24 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
unsigned char random_bytes[64];
unsigned char digest[SHA512_DIGEST_LENGTH];
unsigned done, todo;
- /* We generate |range|+8 bytes of random output. */
- const unsigned num_k_bytes = BN_num_bytes(range) + 8;
+ /* We generate |range|+1 bytes of random output. */
+ const unsigned num_k_bytes = BN_num_bytes(range) + 1;
unsigned char private_bytes[96];
- unsigned char *k_bytes;
+ unsigned char *k_bytes = NULL;
+ const int max_n = 64; /* Pr(failure to generate) < 2^max_n */
+ int n;
int ret = 0;
+ EVP_MD *md = NULL;
+ OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx);
+
+ if (mdctx == NULL)
+ goto end;
k_bytes = OPENSSL_malloc(num_k_bytes);
if (k_bytes == NULL)
- goto err;
+ goto end;
+ /* Ensure top byte is set to avoid non-constant time in bin2bn */
+ k_bytes[0] = 0xff;
/* We copy |priv| into a local buffer to avoid exposing its length. */
if (BN_bn2binpad(priv, private_bytes, sizeof(private_bytes)) < 0) {
@@ -231,35 +332,83 @@ 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);
- goto err;
+ ERR_raise(ERR_LIB_BN, BN_R_PRIVATE_KEY_TOO_LARGE);
+ goto end;
}
- for (done = 0; done < num_k_bytes;) {
- if (RAND_priv_bytes(random_bytes, sizeof(random_bytes)) != 1)
- 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)
- todo = SHA512_DIGEST_LENGTH;
- memcpy(k_bytes + done, digest, todo);
- done += todo;
+ md = EVP_MD_fetch(libctx, "SHA512", NULL);
+ if (md == NULL) {
+ ERR_raise(ERR_LIB_BN, BN_R_NO_SUITABLE_DIGEST);
+ goto end;
}
+ for (n = 0; n < max_n; n++) {
+ unsigned char i = 0;
+
+ for (done = 1; done < num_k_bytes;) {
+ if (RAND_priv_bytes_ex(libctx, random_bytes, sizeof(random_bytes),
+ 0) <= 0)
+ goto end;
+
+ if (!EVP_DigestInit_ex(mdctx, md, NULL)
+ || !EVP_DigestUpdate(mdctx, &i, sizeof(i))
+ || !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 end;
+
+ todo = num_k_bytes - done;
+ if (todo > SHA512_DIGEST_LENGTH)
+ todo = SHA512_DIGEST_LENGTH;
+ memcpy(k_bytes + done, digest, todo);
+ done += todo;
+ ++i;
+ }
- if (!BN_bin2bn(k_bytes, num_k_bytes, out))
- goto err;
- if (BN_mod(out, out, range, ctx) != 1)
- goto err;
- ret = 1;
+ if (!BN_bin2bn(k_bytes, num_k_bytes, out))
+ goto end;
- err:
- OPENSSL_free(k_bytes);
+ /* Clear out the top bits and rejection filter into range */
+ BN_set_flags(out, BN_FLG_CONSTTIME);
+ ossl_bn_mask_bits_fixed_top(out, BN_num_bits(range));
+
+ if (BN_ucmp(out, range) < 0) {
+ ret = 1;
+#ifdef BN_DEBUG
+ /* With BN_DEBUG on a fixed top number cannot be returned */
+ bn_correct_top(out);
+#endif
+ goto end;
+ }
+ }
+ /* Failed to generate anything */
+ ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
+
+ end:
+ 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;
}
+
+int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
+ const BIGNUM *priv, const unsigned char *message,
+ size_t message_len, BN_CTX *ctx)
+{
+ int ret;
+
+ ret = ossl_bn_gen_dsa_nonce_fixed_top(out, range, priv, message,
+ message_len, ctx);
+ /*
+ * This call makes the BN_generate_dsa_nonce non-const-time, thus we
+ * do not use it internally. But fixed_top BNs currently cannot be returned
+ * from public API calls.
+ */
+ bn_correct_top(out);
+ return ret;
+}
diff --git a/crypto/bn/bn_recp.c b/crypto/bn/bn_recp.c
index e82231334123..3a2c812ac666 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-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,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;
}
@@ -44,7 +44,7 @@ void BN_RECP_CTX_free(BN_RECP_CTX *recp)
int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx)
{
- if (!BN_copy(&(recp->N), d))
+ if (BN_is_zero(d) || !BN_copy(&(recp->N), d))
return 0;
BN_zero(&(recp->Nr));
recp->num_bits = BN_num_bits(d);
@@ -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..62d8685d03e0
--- /dev/null
+++ b/crypto/bn/bn_rsa_fips186_4.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2018-2023 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 err;
+ }
+ /* (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..d67331f1f634 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,10 +152,13 @@ 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;
}
+ bn_check_top(r);
+ bn_check_top(a);
+
ret = bn_rshift_fixed_top(r, a, n);
bn_correct_top(r);
@@ -177,9 +180,6 @@ int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n)
BN_ULONG *t, *f;
BN_ULONG l, m, mask;
- bn_check_top(r);
- bn_check_top(a);
-
assert(n >= 0);
nw = n / BN_BITS2;
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..c4ba51b26552 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
+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
deleted file mode 100644
index acafefd5febf..000000000000
--- a/crypto/bn/rsa_sup_mul.c
+++ /dev/null
@@ -1,614 +0,0 @@
-#include <openssl/e_os2.h>
-#include <stddef.h>
-#include <sys/types.h>
-#include <string.h>
-#include <openssl/bn.h>
-#include <openssl/err.h>
-#include <openssl/rsaerr.h>
-#include "internal/numbers.h"
-#include "internal/constant_time.h"
-#include "bn_local.h"
-
-# 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;
-# define HAVE_LIMB2_T
-# endif
-# define LIMB_BIT_SIZE 64
-# define LIMB_BYTE_SIZE 8
-# elif BN_BYTES == 4
-typedef uint32_t limb_t;
-typedef uint64_t limb2_t;
-# define LIMB_BIT_SIZE 32
-# define LIMB_BYTE_SIZE 4
-# define HAVE_LIMB2_T
-# else
-# error "Not supported"
-# endif
-
-/*
- * For multiplication we're using schoolbook multiplication,
- * so if we have two numbers, each with 6 "digits" (words)
- * the multiplication is calculated as follows:
- * A B C D E F
- * x I J K L M N
- * --------------
- * N*F
- * N*E
- * N*D
- * N*C
- * N*B
- * N*A
- * M*F
- * M*E
- * M*D
- * M*C
- * M*B
- * M*A
- * L*F
- * L*E
- * L*D
- * L*C
- * L*B
- * L*A
- * K*F
- * K*E
- * K*D
- * K*C
- * K*B
- * K*A
- * J*F
- * J*E
- * J*D
- * J*C
- * J*B
- * J*A
- * I*F
- * I*E
- * I*D
- * I*C
- * I*B
- * + I*A
- * ==========================
- * N*B N*D N*F
- * + N*A N*C N*E
- * + M*B M*D M*F
- * + M*A M*C M*E
- * + L*B L*D L*F
- * + L*A L*C L*E
- * + K*B K*D K*F
- * + K*A K*C K*E
- * + J*B J*D J*F
- * + J*A J*C J*E
- * + I*B I*D I*F
- * + I*A I*C I*E
- *
- * 1+1 1+3 1+5
- * 1+0 1+2 1+4
- * 0+1 0+3 0+5
- * 0+0 0+2 0+4
- *
- * 0 1 2 3 4 5 6
- * which requires n^2 multiplications and 2n full length additions
- * as we can keep every other result of limb multiplication in two separate
- * limbs
- */
-
-#if defined HAVE_LIMB2_T
-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
-{
- limb2_t t;
- /*
- * this is idiomatic code to tell compiler to use the native mul
- * those three lines will actually compile to single instruction
- */
-
- t = (limb2_t)a * b;
- *hi = t >> LIMB_BIT_SIZE;
- *lo = (limb_t)t;
-}
-#elif (BN_BYTES == 8) && (defined _MSC_VER)
-/* https://learn.microsoft.com/en-us/cpp/intrinsics/umul128?view=msvc-170 */
-#pragma intrinsic(_umul128)
-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
-{
- *lo = _umul128(a, b, hi);
-}
-#else
-/*
- * if the compiler doesn't have either a 128bit data type nor a "return
- * high 64 bits of multiplication"
- */
-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
-{
- limb_t a_low = (limb_t)(uint32_t)a;
- limb_t a_hi = a >> 32;
- limb_t b_low = (limb_t)(uint32_t)b;
- limb_t b_hi = b >> 32;
-
- limb_t p0 = a_low * b_low;
- limb_t p1 = a_low * b_hi;
- limb_t p2 = a_hi * b_low;
- limb_t p3 = a_hi * b_hi;
-
- uint32_t cy = (uint32_t)(((p0 >> 32) + (uint32_t)p1 + (uint32_t)p2) >> 32);
-
- *lo = p0 + (p1 << 32) + (p2 << 32);
- *hi = p3 + (p1 >> 32) + (p2 >> 32) + cy;
-}
-#endif
-
-/* add two limbs with carry in, return carry out */
-static ossl_inline limb_t _add_limb(limb_t *ret, limb_t a, limb_t b, limb_t carry)
-{
- limb_t carry1, carry2, t;
- /*
- * `c = a + b; if (c < a)` is idiomatic code that makes compilers
- * use add with carry on assembly level
- */
-
- *ret = a + carry;
- if (*ret < a)
- carry1 = 1;
- else
- carry1 = 0;
-
- t = *ret;
- *ret = t + b;
- if (*ret < t)
- carry2 = 1;
- else
- carry2 = 0;
-
- return carry1 + carry2;
-}
-
-/*
- * add two numbers of the same size, return overflow
- *
- * add a to b, place result in ret; all arrays need to be n limbs long
- * return overflow from addition (0 or 1)
- */
-static ossl_inline limb_t add(limb_t *ret, limb_t *a, limb_t *b, size_t n)
-{
- limb_t c = 0;
- ossl_ssize_t i;
-
- for(i = n - 1; i > -1; i--)
- c = _add_limb(&ret[i], a[i], b[i], c);
-
- return c;
-}
-
-/*
- * return number of limbs necessary for temporary values
- * when multiplying numbers n limbs large
- */
-static ossl_inline size_t mul_limb_numb(size_t n)
-{
- return 2 * n * 2;
-}
-
-/*
- * multiply two numbers of the same size
- *
- * multiply a by b, place result in ret; a and b need to be n limbs long
- * ret needs to be 2*n limbs long, tmp needs to be mul_limb_numb(n) limbs
- * long
- */
-static void limb_mul(limb_t *ret, limb_t *a, limb_t *b, size_t n, limb_t *tmp)
-{
- limb_t *r_odd, *r_even;
- size_t i, j, k;
-
- r_odd = tmp;
- r_even = &tmp[2 * n];
-
- memset(ret, 0, 2 * n * sizeof(limb_t));
-
- for (i = 0; i < n; i++) {
- for (k = 0; k < i + n + 1; k++) {
- r_even[k] = 0;
- r_odd[k] = 0;
- }
- for (j = 0; j < n; j++) {
- /*
- * place results from even and odd limbs in separate arrays so that
- * we don't have to calculate overflow every time we get individual
- * limb multiplication result
- */
- if (j % 2 == 0)
- _mul_limb(&r_even[i + j], &r_even[i + j + 1], a[i], b[j]);
- else
- _mul_limb(&r_odd[i + j], &r_odd[i + j + 1], a[i], b[j]);
- }
- /*
- * skip the least significant limbs when adding multiples of
- * more significant limbs (they're zero anyway)
- */
- add(ret, ret, r_even, n + i + 1);
- add(ret, ret, r_odd, n + i + 1);
- }
-}
-
-/* modifies the value in place by performing a right shift by one bit */
-static ossl_inline void rshift1(limb_t *val, size_t n)
-{
- limb_t shift_in = 0, shift_out = 0;
- size_t i;
-
- for (i = 0; i < n; i++) {
- shift_out = val[i] & 1;
- val[i] = shift_in << (LIMB_BIT_SIZE - 1) | (val[i] >> 1);
- shift_in = shift_out;
- }
-}
-
-/* extend the LSB of flag to all bits of limb */
-static ossl_inline limb_t mk_mask(limb_t flag)
-{
- flag |= flag << 1;
- flag |= flag << 2;
- flag |= flag << 4;
- flag |= flag << 8;
- flag |= flag << 16;
-#if (LIMB_BYTE_SIZE == 8)
- flag |= flag << 32;
-#endif
- return flag;
-}
-
-/*
- * copy from either a or b to ret based on flag
- * when flag == 0, then copies from b
- * when flag == 1, then copies from a
- */
-static ossl_inline void cselect(limb_t flag, limb_t *ret, limb_t *a, limb_t *b, size_t n)
-{
- /*
- * would be more efficient with non volatile mask, but then gcc
- * generates code with jumps
- */
- volatile limb_t mask;
- size_t i;
-
- mask = mk_mask(flag);
- for (i = 0; i < n; i++) {
-#if (LIMB_BYTE_SIZE == 8)
- ret[i] = constant_time_select_64(mask, a[i], b[i]);
-#else
- ret[i] = constant_time_select_32(mask, a[i], b[i]);
-#endif
- }
-}
-
-static limb_t _sub_limb(limb_t *ret, limb_t a, limb_t b, limb_t borrow)
-{
- limb_t borrow1, borrow2, t;
- /*
- * while it doesn't look constant-time, this is idiomatic code
- * to tell compilers to use the carry bit from subtraction
- */
-
- *ret = a - borrow;
- if (*ret > a)
- borrow1 = 1;
- else
- borrow1 = 0;
-
- t = *ret;
- *ret = t - b;
- if (*ret > t)
- borrow2 = 1;
- else
- borrow2 = 0;
-
- return borrow1 + borrow2;
-}
-
-/*
- * place the result of a - b into ret, return the borrow bit.
- * All arrays need to be n limbs long
- */
-static limb_t sub(limb_t *ret, limb_t *a, limb_t *b, size_t n)
-{
- limb_t borrow = 0;
- ossl_ssize_t i;
-
- for (i = n - 1; i > -1; i--)
- borrow = _sub_limb(&ret[i], a[i], b[i], borrow);
-
- return borrow;
-}
-
-/* return the number of limbs necessary to allocate for the mod() tmp operand */
-static ossl_inline size_t mod_limb_numb(size_t anum, size_t modnum)
-{
- return (anum + modnum) * 3;
-}
-
-/*
- * calculate a % mod, place the result in ret
- * size of a is defined by anum, size of ret and mod is modnum,
- * size of tmp is returned by mod_limb_numb()
- */
-static void mod(limb_t *ret, limb_t *a, size_t anum, limb_t *mod,
- size_t modnum, limb_t *tmp)
-{
- limb_t *atmp, *modtmp, *rettmp;
- limb_t res;
- size_t i;
-
- memset(tmp, 0, mod_limb_numb(anum, modnum) * LIMB_BYTE_SIZE);
-
- atmp = tmp;
- modtmp = &tmp[anum + modnum];
- rettmp = &tmp[(anum + modnum) * 2];
-
- for (i = modnum; i <modnum + anum; i++)
- atmp[i] = a[i-modnum];
-
- for (i = 0; i < modnum; i++)
- modtmp[i] = mod[i];
-
- for (i = 0; i < anum * LIMB_BIT_SIZE; i++) {
- rshift1(modtmp, anum + modnum);
- res = sub(rettmp, atmp, modtmp, anum+modnum);
- cselect(res, atmp, atmp, rettmp, anum+modnum);
- }
-
- memcpy(ret, &atmp[anum], sizeof(limb_t) * modnum);
-}
-
-/* necessary size of tmp for a _mul_add_limb() call with provided anum */
-static ossl_inline size_t _mul_add_limb_numb(size_t anum)
-{
- return 2 * (anum + 1);
-}
-
-/* multiply a by m, add to ret, return carry */
-static limb_t _mul_add_limb(limb_t *ret, limb_t *a, size_t anum,
- limb_t m, limb_t *tmp)
-{
- limb_t carry = 0;
- limb_t *r_odd, *r_even;
- size_t i;
-
- memset(tmp, 0, sizeof(limb_t) * (anum + 1) * 2);
-
- r_odd = tmp;
- r_even = &tmp[anum + 1];
-
- for (i = 0; i < anum; i++) {
- /*
- * place the results from even and odd limbs in separate arrays
- * so that we have to worry about carry just once
- */
- if (i % 2 == 0)
- _mul_limb(&r_even[i], &r_even[i + 1], a[i], m);
- else
- _mul_limb(&r_odd[i], &r_odd[i + 1], a[i], m);
- }
- /* assert: add() carry here will be equal zero */
- add(r_even, r_even, r_odd, anum + 1);
- /*
- * while here it will not overflow as the max value from multiplication
- * is -2 while max overflow from addition is 1, so the max value of
- * carry is -1 (i.e. max int)
- */
- carry = add(ret, ret, &r_even[1], anum) + r_even[0];
-
- return carry;
-}
-
-static ossl_inline size_t mod_montgomery_limb_numb(size_t modnum)
-{
- return modnum * 2 + _mul_add_limb_numb(modnum);
-}
-
-/*
- * calculate a % mod, place result in ret
- * assumes that a is in Montgomery form with the R (Montgomery modulus) being
- * smallest power of two big enough to fit mod and that's also a power
- * of the count of number of bits in limb_t (B).
- * For calculation, we also need n', such that mod * n' == -1 mod B.
- * anum must be <= 2 * modnum
- * ret needs to be modnum words long
- * tmp needs to be mod_montgomery_limb_numb(modnum) limbs long
- */
-static void mod_montgomery(limb_t *ret, limb_t *a, size_t anum, limb_t *mod,
- size_t modnum, limb_t ni0, limb_t *tmp)
-{
- limb_t carry, v;
- limb_t *res, *rp, *tmp2;
- ossl_ssize_t i;
-
- res = tmp;
- /*
- * for intermediate result we need an integer twice as long as modulus
- * but keep the input in the least significant limbs
- */
- memset(res, 0, sizeof(limb_t) * (modnum * 2));
- memcpy(&res[modnum * 2 - anum], a, sizeof(limb_t) * anum);
- rp = &res[modnum];
- tmp2 = &res[modnum * 2];
-
- carry = 0;
-
- /* 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 = v + carry + rp[-1];
- carry |= (v != rp[-1]);
- carry &= (v <= rp[-1]);
- rp[-1] = v;
- }
-
- /* perform the final reduction by mod... */
- carry -= sub(ret, rp, mod, modnum);
-
- /* ...conditionally */
- cselect(carry, ret, rp, ret, modnum);
-}
-
-/* allocated buffer should be freed afterwards */
-static void BN_to_limb(const BIGNUM *bn, limb_t *buf, size_t limbs)
-{
- int i;
- int real_limbs = (BN_num_bytes(bn) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE;
- limb_t *ptr = buf + (limbs - real_limbs);
-
- for (i = 0; i < real_limbs; i++)
- ptr[i] = bn->d[real_limbs - i - 1];
-}
-
-#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 {
- return host;
- }
-}
-
-#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 {
- return host;
- }
-}
-#endif
-
-/*
- * We assume that intermediate, possible_arg2, blinding, and ctx are used
- * similar to BN_BLINDING_invert_ex() arguments.
- * to_mod is RSA modulus.
- * buf and num is the serialization buffer and its length.
- *
- * Here we use classic/Montgomery multiplication and modulo. After the calculation finished
- * we serialize the new structure instead of BIGNUMs taking endianness into account.
- */
-int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate,
- const BN_BLINDING *blinding,
- const BIGNUM *possible_arg2,
- const BIGNUM *to_mod, BN_CTX *ctx,
- unsigned char *buf, int num)
-{
- limb_t *l_im = NULL, *l_mul = NULL, *l_mod = NULL;
- limb_t *l_ret = NULL, *l_tmp = NULL, l_buf;
- size_t l_im_count = 0, l_mul_count = 0, l_size = 0, l_mod_count = 0;
- size_t l_tmp_count = 0;
- int ret = 0;
- size_t i;
- unsigned char *tmp;
- const BIGNUM *arg1 = intermediate;
- const BIGNUM *arg2 = (possible_arg2 == NULL) ? blinding->Ai : possible_arg2;
-
- l_im_count = (BN_num_bytes(arg1) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE;
- l_mul_count = (BN_num_bytes(arg2) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE;
- l_mod_count = (BN_num_bytes(to_mod) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE;
-
- l_size = l_im_count > l_mul_count ? l_im_count : l_mul_count;
- l_im = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE);
- l_mul = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE);
- l_mod = OPENSSL_zalloc(l_mod_count * LIMB_BYTE_SIZE);
-
- if ((l_im == NULL) || (l_mul == NULL) || (l_mod == NULL))
- goto err;
-
- BN_to_limb(arg1, l_im, l_size);
- BN_to_limb(arg2, l_mul, l_size);
- BN_to_limb(to_mod, l_mod, l_mod_count);
-
- l_ret = OPENSSL_malloc(2 * l_size * LIMB_BYTE_SIZE);
-
- if (blinding->m_ctx != NULL) {
- l_tmp_count = mul_limb_numb(l_size) > mod_montgomery_limb_numb(l_mod_count) ?
- mul_limb_numb(l_size) : mod_montgomery_limb_numb(l_mod_count);
- l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE);
- } else {
- l_tmp_count = mul_limb_numb(l_size) > mod_limb_numb(2 * l_size, l_mod_count) ?
- mul_limb_numb(l_size) : mod_limb_numb(2 * l_size, l_mod_count);
- l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE);
- }
-
- if ((l_ret == NULL) || (l_tmp == NULL))
- goto err;
-
- if (blinding->m_ctx != NULL) {
- limb_mul(l_ret, l_im, l_mul, l_size, l_tmp);
- mod_montgomery(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count,
- blinding->m_ctx->n0[0], l_tmp);
- } else {
- limb_mul(l_ret, l_im, l_mul, l_size, l_tmp);
- mod(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count, l_tmp);
- }
-
- /* 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);
- goto err;
- }
-
- memset(buf, 0, num);
- tmp = buf + num - BN_num_bytes(to_mod);
- for (i = 0; i < l_mod_count; i++) {
-#if LIMB_BYTE_SIZE == 8
- l_buf = be64(l_ret[i]);
-#else
- l_buf = be32(l_ret[i]);
-#endif
- if (i == 0) {
- int delta = LIMB_BYTE_SIZE - ((l_mod_count * LIMB_BYTE_SIZE) - num);
-
- memcpy(tmp, ((char *)&l_buf) + LIMB_BYTE_SIZE - delta, delta);
- tmp += delta;
- } else {
- memcpy(tmp, &l_buf, LIMB_BYTE_SIZE);
- tmp += LIMB_BYTE_SIZE;
- }
- }
- ret = num;
-
- err:
- OPENSSL_free(l_im);
- OPENSSL_free(l_mul);
- OPENSSL_free(l_mod);
- OPENSSL_free(l_tmp);
- OPENSSL_free(l_ret);
-
- return ret;
-}
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..4a2a6752f672
--- /dev/null
+++ b/crypto/bn/rsaz_exp_x2.c
@@ -0,0 +1,571 @@
+/*
+ * Copyright 2020-2025 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--;
+ }
+
+ memset(out, 0, out_len * sizeof(BN_ULONG));
+}
+
+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..a45bf8deefd5 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -1,39 +1,136 @@
+# 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/legacy]=$CPUID_COMMON
+ DEFINE[../providers/legacy]=$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
+
+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..78201649d550
--- /dev/null
+++ b/crypto/chacha/asm/chacha-ia64.pl
@@ -0,0 +1,293 @@
+#!/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 $out=0,$out
+ ADDP $inp=0,$inp }
+{ .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..a8de73ad979b
--- /dev/null
+++ b/crypto/cmp/cmp_asn.c
@@ -0,0 +1,459 @@
+/*
+ * 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 <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 -2 on error; -1 is valid for certReqId */
+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 -2;
+ }
+ if (res < INT_MIN) {
+ ERR_raise(ERR_LIB_CMP, ASN1_R_TOO_SMALL);
+ return -2;
+ }
+ if (res > INT_MAX) {
+ ERR_raise(ERR_LIB_CMP, ASN1_R_TOO_LARGE);
+ return -2;
+ }
+ 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..8950091b93ee
--- /dev/null
+++ b/crypto/cmp/cmp_client.c
@@ -0,0 +1,923 @@
+/*
+ * Copyright 2007-2025 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)) {
+ int any_rid = OSSL_CMP_CERTREQID_NONE;
+ OSSL_CMP_CERTREPMESSAGE *crepmsg = rep->body->value.ip;
+ OSSL_CMP_CERTRESPONSE *crep =
+ ossl_cmp_certrepmessage_get0_certresponse(crepmsg, 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);
+ ASN1_UTF8STRING *dup = ASN1_STRING_dup(str);
+
+ if (dup == NULL || !sk_ASN1_UTF8STRING_push(ctx->statusString, dup)) {
+ ASN1_UTF8STRING_free(dup);
+ 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 certReqId,
+ 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 */
+ certConf = ossl_cmp_certConf_new(ctx, certReqId, fail_info, txt);
+ if (certConf == 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;
+
+ if (!ossl_assert(ctx != NULL && crep != NULL))
+ return NULL;
+
+ 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(ctx, crep);
+ 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;
+
+ if (out_trusted == NULL) {
+ ossl_cmp_debug(ctx, "trying to build chain for newly enrolled cert");
+ chain = X509_build_chain(cert, ctx->untrusted, out_trusted,
+ 0, ctx->libctx, ctx->propq);
+ } else {
+ X509_STORE_CTX *csc = X509_STORE_CTX_new_ex(ctx->libctx, ctx->propq);
+
+ ossl_cmp_debug(ctx, "validating newly enrolled cert");
+ if (csc == NULL)
+ goto err;
+ if (!X509_STORE_CTX_init(csc, out_trusted, cert, ctx->untrusted))
+ goto err;
+ /* disable any cert status/revocation checking etc. */
+ X509_VERIFY_PARAM_clear_flags(X509_STORE_CTX_get0_param(csc),
+ ~(X509_V_FLAG_USE_CHECK_TIME
+ | X509_V_FLAG_NO_CHECK_TIME
+ | X509_V_FLAG_PARTIAL_CHAIN
+ | X509_V_FLAG_POLICY_CHECK));
+ if (X509_verify_cert(csc) <= 0)
+ goto err;
+
+ if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc),
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
+ | X509_ADD_FLAG_NO_SS)) {
+ sk_X509_free(chain);
+ chain = NULL;
+ }
+ err:
+ X509_STORE_CTX_free(csc);
+ }
+
+ 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 to validate newly enrolled cert");
+ fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
+ } else {
+ ossl_cmp_debug(ctx,
+ "success validating 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.
+ * |rid| must be OSSL_CMP_CERTREQID_NONE if not available, namely for 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_newPubkey(ctx);
+ 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 == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */
+ rid = ossl_cmp_asn1_get_int(crep->certReqId);
+ if (rid < OSSL_CMP_CERTREQID_NONE) {
+ 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)) {
+ X509_free(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, rid, 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);
+ ctx->status = OSSL_CMP_PKISTATUS_rejection;
+ 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 ? OSSL_CMP_CERTREQID_NONE : 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 ? OSSL_CMP_CERTREQID_NONE : 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..9d9bd357daf7
--- /dev/null
+++ b/crypto/cmp/cmp_ctx.c
@@ -0,0 +1,1173 @@
+/*
+ * 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 <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, 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 to be placed 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 to be placed in the certTemplate */
+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 */
+/* In case |priv| == 0, better use ossl_cmp_ctx_get0_newPubkey() below */
+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 */
+}
+
+EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx)
+{
+ if (!ossl_assert(ctx != NULL))
+ return NULL;
+ if (ctx->newPkey != NULL)
+ return ctx->newPkey;
+ if (ctx->p10CSR != NULL)
+ return X509_REQ_get0_pubkey(ctx->p10CSR);
+ if (ctx->oldCert != NULL)
+ return X509_get0_pubkey(ctx->oldCert);
+ if (ctx->cert != NULL)
+ return X509_get0_pubkey(ctx->cert);
+ return ctx->pkey;
+}
+
+/* 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..dfc6dfbedee9
--- /dev/null
+++ b/crypto/cmp/cmp_err.c
@@ -0,0 +1,181 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-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/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_PRIVATE_KEY_FOR_POPO),
+ "missing private key for popo"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PROTECTION), "missing protection"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PUBLIC_KEY), "missing public key"},
+ {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..8eeb56d4e0f0
--- /dev/null
+++ b/crypto/cmp/cmp_local.h
@@ -0,0 +1,933 @@
+/*
+ * 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
+ */
+
+#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);
+EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx);
+
+/* 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
+# define OSSL_CMP_CERTREQID_NONE -1
+# define OSSL_CMP_CERTREQID_INVALID -2
+/* 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 certReqId,
+ 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_CTX *ctx,
+ const OSSL_CMP_CERTRESPONSE *crep);
+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 certReqId,
+ 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..c8e467f3c21f
--- /dev/null
+++ b/crypto/cmp/cmp_msg.c
@@ -0,0 +1,1180 @@
+/*
+ * 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
+ */
+
+/* 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_newPubkey(ctx);
+ 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) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PUBLIC_KEY);
+ 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 ctx->newPkey (if private, else NULL) or ctx->pkey */
+ if (ctx->popoMethod >= OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY_FOR_POPO);
+ 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 certReqId,
+ 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
+ && (certReqId == OSSL_CMP_CERTREQID
+ || certReqId == OSSL_CMP_CERTREQID_NONE)))
+ 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) < 1) {
+ OSSL_CMP_CERTSTATUS_free(certStatus);
+ goto err;
+ }
+
+ /* set the ID of the certReq */
+ if (!ASN1_INTEGER_set(certStatus->certReqId, 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 == OSSL_CMP_CERTREQID_NONE)
+ return 1;
+
+ trid = ossl_cmp_asn1_get_int(certReqId);
+
+ if (trid == OSSL_CMP_CERTREQID_NONE) {
+ 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.
+ * Uses libctx and propq from ctx, in case of indirect POPO also 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_CTX *ctx,
+ const OSSL_CMP_CERTRESPONSE *crep)
+{
+ OSSL_CMP_CERTORENCCERT *coec;
+ X509 *crt = NULL;
+ EVP_PKEY *pkey;
+
+ 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 */
+ pkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
+ /* pkey is ctx->newPkey (if private, else NULL) or ctx->pkey */
+ 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);
+}
+
+int OSSL_CMP_MSG_update_recipNonce(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
+{
+ if (ctx == NULL || msg == NULL || msg->header == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ctx->recipNonce == NULL) /* nothing to do for 1st msg in transaction */
+ return 1;
+ if (!ossl_cmp_asn1_octet_string_set1(&msg->header->recipNonce,
+ ctx->recipNonce))
+ 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..539f6534cd01
--- /dev/null
+++ b/crypto/cmp/cmp_protect.c
@@ -0,0 +1,334 @@
+/*
+ * 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"
+
+/* 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;
+ }
+}
+
+/* ctx is not const just because ctx->chain may get adapted */
+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);
+}
+
+/* ctx is not const just because ctx->chain may get adapted */
+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..96f977636ca2
--- /dev/null
+++ b/crypto/cmp/cmp_server.c
@@ -0,0 +1,665 @@
+/*
+ * 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
+ */
+
+/* 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
+{
+ void *custom_ctx; /* pointer to application-specific server context */
+ OSSL_CMP_CTX *ctx; /* Client CMP context, reusing transactionID etc. */
+ int certReqId; /* id of last ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */
+
+ 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;
+ ctx->certReqId = OSSL_CMP_CERTREQID_INVALID;
+
+ /* 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_NONE; /* p10cr does not include an Id */
+ 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 (certReqId != OSSL_CMP_CERTREQID) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return 0;
+ }
+ }
+ srv_ctx->certReqId = certReqId;
+
+ 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 (certReqId != srv_ctx->certReqId) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return NULL;
+ }
+ 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, OSSL_CMP_CERTREQID);
+ certReqId = ossl_cmp_asn1_get_int(pr->certReqId);
+ if (certReqId != srv_ctx->certReqId) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return NULL;
+ }
+ 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 req_verified = 0;
+ 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
+ }
+ }
+
+ req_verified = 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 (!req_verified)
+ 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 (!req_verified) {
+ /*
+ * Above ossl_cmp_msg_check_update() was not successfully executed,
+ * which normally would set ctx->transactionID and ctx->recipNonce.
+ * So anyway try to provide the right transactionID and recipNonce,
+ * while ignoring any (extra) error in next two function calls.
+ */
+ if (ctx->transactionID == NULL)
+ (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..68144aa4fed8
--- /dev/null
+++ b/crypto/cmp/cmp_status.c
@@ -0,0 +1,317 @@
+/*
+ * 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
+ */
+
+/* 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)
+{
+ int res ;
+
+ if (!ossl_assert(si != NULL && si->status != NULL))
+ return -1;
+ res = ossl_cmp_asn1_get_int(si->status);
+ return res == -2 ? -1 : res;
+}
+
+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..b9951045c2e8
--- /dev/null
+++ b/crypto/cmp/cmp_vfy.c
@@ -0,0 +1,855 @@
+/*
+ * Copyright 2007-2024 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
+ */
+ OSSL_CMP_CERTRESPONSE *crep =
+ ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip,
+ OSSL_CMP_CERTREQID);
+ X509 *newcrt = ossl_cmp_certresponse_get1_cert(ctx, crep);
+
+ /*
+ * 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 && ctx->secretValue != 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
+ }
+
+ /* if not yet present, learn transactionID */
+ if (ctx->transactionID == NULL
+ && !OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID))
+ return 0;
+
+ /*
+ * 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;
+
+ /*
+ * 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 0;
+
+ 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..950952015923 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
@@ -51,6 +51,7 @@ static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
EVP_PKEY_free(si->pkey);
X509_free(si->signer);
EVP_MD_CTX_free(si->mctx);
+ EVP_PKEY_CTX_free(si->pctx);
}
return 1;
}
@@ -89,11 +90,21 @@ ASN1_SEQUENCE(CMS_OriginatorInfo) = {
ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, crls, CMS_RevocationInfoChoice, 1)
} static_ASN1_SEQUENCE_END(CMS_OriginatorInfo)
-ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = {
+static int cms_ec_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+{
+ CMS_EncryptedContentInfo *ec = (CMS_EncryptedContentInfo *)*pval;
+
+ if (operation == ASN1_OP_FREE_POST)
+ OPENSSL_clear_free(ec->key, ec->keylen);
+ return 1;
+}
+
+ASN1_NDEF_SEQUENCE_cb(CMS_EncryptedContentInfo, cms_ec_cb) = {
ASN1_SIMPLE(CMS_EncryptedContentInfo, contentType, ASN1_OBJECT),
ASN1_SIMPLE(CMS_EncryptedContentInfo, contentEncryptionAlgorithm, X509_ALGOR),
ASN1_IMP_OPT(CMS_EncryptedContentInfo, encryptedContent, ASN1_OCTET_STRING_NDEF, 0)
-} static_ASN1_NDEF_SEQUENCE_END(CMS_EncryptedContentInfo)
+} ASN1_NDEF_SEQUENCE_END_cb(CMS_EncryptedContentInfo, CMS_EncryptedContentInfo)
ASN1_SEQUENCE(CMS_KeyTransRecipientInfo) = {
ASN1_EMBED(CMS_KeyTransRecipientInfo, version, INT32),
@@ -245,6 +256,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 +295,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);
@@ -305,6 +328,10 @@ static int cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
return 0;
break;
+ case ASN1_OP_FREE_POST:
+ OPENSSL_free(cms->ctx.propq);
+ break;
+
}
return 1;
}
diff --git a/crypto/cms/cms_att.c b/crypto/cms/cms_att.c
index 4f716619193a..64acda72630a 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,9 @@
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
-#include "cms_local.h"
#include "internal/nelem.h"
+#include "crypto/x509.h"
+#include "cms_local.h"
/*-
* Attribute flags.
@@ -94,7 +95,7 @@ X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc)
int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr)
{
- if (X509at_add1_attr(&si->signedAttrs, attr))
+ if (ossl_x509at_add1_attr(&si->signedAttrs, attr))
return 1;
return 0;
}
@@ -103,7 +104,7 @@ int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
const ASN1_OBJECT *obj, int type,
const void *bytes, int len)
{
- if (X509at_add1_attr_by_OBJ(&si->signedAttrs, obj, type, bytes, len))
+ if (ossl_x509at_add1_attr_by_OBJ(&si->signedAttrs, obj, type, bytes, len))
return 1;
return 0;
}
@@ -111,7 +112,7 @@ int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
int nid, int type, const void *bytes, int len)
{
- if (X509at_add1_attr_by_NID(&si->signedAttrs, nid, type, bytes, len))
+ if (ossl_x509at_add1_attr_by_NID(&si->signedAttrs, nid, type, bytes, len))
return 1;
return 0;
}
@@ -120,12 +121,14 @@ int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
const char *attrname, int type,
const void *bytes, int len)
{
- if (X509at_add1_attr_by_txt(&si->signedAttrs, attrname, type, bytes, len))
+ if (ossl_x509at_add1_attr_by_txt(&si->signedAttrs, attrname, type, bytes,
+ len))
return 1;
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);
@@ -160,7 +163,7 @@ X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc)
int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr)
{
- if (X509at_add1_attr(&si->unsignedAttrs, attr))
+ if (ossl_x509at_add1_attr(&si->unsignedAttrs, attr))
return 1;
return 0;
}
@@ -169,7 +172,7 @@ int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si,
const ASN1_OBJECT *obj, int type,
const void *bytes, int len)
{
- if (X509at_add1_attr_by_OBJ(&si->unsignedAttrs, obj, type, bytes, len))
+ if (ossl_x509at_add1_attr_by_OBJ(&si->unsignedAttrs, obj, type, bytes, len))
return 1;
return 0;
}
@@ -178,7 +181,7 @@ int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si,
int nid, int type,
const void *bytes, int len)
{
- if (X509at_add1_attr_by_NID(&si->unsignedAttrs, nid, type, bytes, len))
+ if (ossl_x509at_add1_attr_by_NID(&si->unsignedAttrs, nid, type, bytes, len))
return 1;
return 0;
}
@@ -187,8 +190,8 @@ int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
const char *attrname, int type,
const void *bytes, int len)
{
- if (X509at_add1_attr_by_txt(&si->unsignedAttrs, attrname,
- type, bytes, len))
+ if (ossl_x509at_add1_attr_by_txt(&si->unsignedAttrs, attrname,
+ type, bytes, len))
return 1;
return 0;
}
@@ -262,7 +265,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 +279,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..3f931d6e6fef
--- /dev/null
+++ b/crypto/cms/cms_dh.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2006-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/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 (penclen <= 0)
+ goto err;
+ wrap_str = ASN1_STRING_new();
+ if (wrap_str == NULL)
+ goto err;
+ ASN1_STRING_set0(wrap_str, penc, penclen);
+ penc = NULL;
+ rv = X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
+ V_ASN1_SEQUENCE, wrap_str);
+ if (!rv)
+ ASN1_STRING_free(wrap_str);
+
+ 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..d5ebe1ced0a6
--- /dev/null
+++ b/crypto/cms/cms_ec.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright 2006-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 <limits.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;
+ 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 == 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 */
+ size_t enckeylen;
+
+ enckeylen = EVP_PKEY_get1_encoded_public_key(pkey, &penc);
+ if (enckeylen > INT_MAX || enckeylen == 0)
+ goto err;
+ ASN1_STRING_set0(pubkey, penc, (int)enckeylen);
+ pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+ penc = NULL;
+ (void)X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
+ V_ASN1_UNDEF, NULL); /* cannot fail */
+ }
+
+ /* 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 (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..ae88df33a7f0 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-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
@@ -14,84 +14,115 @@
#include <openssl/err.h>
#include <openssl/cms.h>
#include <openssl/rand.h>
+#include "crypto/evp.h"
+#include "crypto/asn1.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));
- if (calg->algorithm == NULL) {
- CMSerr(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM);
+ calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx));
+ if (calg->algorithm == NULL || calg->algorithm->nid == NID_undef) {
+ 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 +148,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 +162,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 +192,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 +204,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 +227,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..445a16fb771f 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.
+ * 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
@@ -13,29 +13,68 @@
#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_simple(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;
+
+ default:
+ return 0;
+ }
+}
+
+static int cms_get_enveloped_type(const CMS_ContentInfo *cms)
+{
+ int ret = cms_get_enveloped_type_simple(cms);
+
+ if (ret == 0)
+ ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
+ return ret;
+}
-CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
+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 +84,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);
+}
+
+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 cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
+int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
{
EVP_PKEY *pkey;
int i;
@@ -56,35 +115,98 @@ 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 == NULL ? NULL
+ : cms->d.envelopedData->encryptedContentInfo;
+
+ case CMS_ENVELOPED_AUTH:
+ return cms->d.authEnvelopedData == NULL ? NULL
+ : 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 +223,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);
- CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
+ 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);
+ 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 +299,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 +314,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 +324,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 +340,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 +430,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 +461,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 +469,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 +496,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 +519,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 +532,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);
+
+ (void)ERR_set_mark();
+ fetched_cipher = EVP_CIPHER_fetch(libctx, name, propq);
- if (ciph == NULL) {
- CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_UNKNOWN_CIPHER);
+ 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 +587,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 +597,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 +624,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 +662,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 +683,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 +692,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 +721,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 +746,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 +761,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 +791,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 +801,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 +886,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 +901,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 +968,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 +986,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 +1078,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);
-
- /* If error or no cipher end of processing */
+ ec = env->encryptedContentInfo;
+ ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms));
- 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);
}
- cms_env_set_version(cms->d.envelopedData);
+
+ /* 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;
+ }
+
+ /* 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 +1298,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 +1324,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..e67d783be290 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,215 +10,89 @@
#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"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ATTRIBUTE_ERROR), "attribute error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_ALREADY_PRESENT),
- "certificate already present"},
+ "certificate already present"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_HAS_NO_KEYID),
- "certificate has no keyid"},
+ "certificate has no keyid"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_VERIFY_ERROR),
- "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"},
+ "cipher initialisation error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),
- "cipher parameter initialisation error"},
+ "cipher parameter initialisation error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CMS_DATAFINAL_ERROR),
- "cms datafinal error"},
+ "cms datafinal error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CMS_LIB), "cms lib"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENTIDENTIFIER_MISMATCH),
- "contentidentifier mismatch"},
+ "contentidentifier mismatch"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_NOT_FOUND), "content not found"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_MISMATCH),
- "content type mismatch"},
+ "content type mismatch"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA),
- "content type not compressed data"},
+ "content type not compressed data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA),
- "content type not enveloped data"},
+ "content type not enveloped data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA),
- "content type not signed data"},
+ "content type not signed data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_VERIFY_ERROR),
- "content verify error"},
+ "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"},
+ "error getting public key"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),
- "error reading messagedigest attribute"},
+ "error reading messagedigest attribute"},
{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"},
+ "error setting recipientinfo"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT),
+ "error unsupported static key agreement"},
+ {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"},
+ "invalid encrypted key length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),
- "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"},
+ "messagedigest attribute wrong length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MESSAGEDIGEST_WRONG_LENGTH),
- "messagedigest wrong length"},
+ "messagedigest wrong length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_ERROR), "msgsigdigest error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE),
- "msgsigdigest verification failure"},
+ "msgsigdigest verification failure"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_WRONG_LENGTH),
- "msgsigdigest wrong length"},
+ "msgsigdigest wrong length"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NEED_ONE_SIGNER), "need one signer"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_A_SIGNED_RECEIPT),
- "not a signed receipt"},
+ "not a signed receipt"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_ENCRYPTED_DATA), "not encrypted data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEK), "not kek"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEY_AGREEMENT), "not key agreement"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEY_TRANSPORT), "not key transport"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_PWRI), "not pwri"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),
- "not supported for this key type"},
+ "not supported for this key type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CIPHER), "no cipher"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CONTENT), "no content"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CONTENT_TYPE), "no content type"},
@@ -228,72 +102,81 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_KEY_OR_CERT), "no key or cert"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_DIGEST), "no matching digest"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_RECIPIENT),
- "no matching recipient"},
+ "no matching recipient"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_SIGNATURE),
- "no matching signature"},
+ "no matching signature"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MSGSIGDIGEST), "no msgsigdigest"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PASSWORD), "no password"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PRIVATE_KEY), "no private key"},
{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"},
+ "private key does not match certificate"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECEIPT_DECODE_ERROR),
- "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"},
+ "signer certificate not found"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNFINAL_ERROR), "signfinal error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SMIME_TEXT_ERROR), "smime text error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_STORE_INIT_ERROR), "store init error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_COMPRESSED_DATA),
- "type not compressed data"},
+ "type not compressed data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_DATA), "type not data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_DIGESTED_DATA),
- "type not digested data"},
+ "type not digested data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_ENCRYPTED_DATA),
- "type not encrypted data"},
+ "type not encrypted data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_ENVELOPED_DATA),
- "type not enveloped data"},
+ "type not enveloped data"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNABLE_TO_FINALIZE_CONTEXT),
- "unable to finalize context"},
+ "unable to finalize context"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_CIPHER), "unknown cipher"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_DIGEST_ALGORITHM),
- "unknown digest algorithm"},
+ "unknown digest algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_ID), "unknown id"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),
- "unsupported compression algorithm"},
+ "unsupported compression algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM),
- "unsupported content encryption algorithm"},
+ "unsupported content encryption algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_TYPE),
- "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"},
+ "unsupported kek algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),
- "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"},
+ "unsupported recipientinfo type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENT_TYPE),
- "unsupported recipient type"},
+ "unsupported recipient type"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM),
+ "unsupported signature algorithm"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_TYPE), "unsupported type"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNWRAP_ERROR), "unwrap error"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNWRAP_FAILURE), "unwrap failure"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_VERIFICATION_FAILURE),
- "verification failure"},
+ "verification failure"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_WRAP_ERROR), "wrap error"},
{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..8e9e6a5d148c 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
+
+ if (originatorPrivKey == NULL || originator == NULL)
+ return 0;
- EVP_PKEY_up_ref(pk);
- rek->pkey = pk;
+ 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;
@@ -392,9 +502,16 @@ int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms,
oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey);
if (!oik->d.originatorKey)
return 0;
+ } else {
+ /*
+ * Currently it is not possible to get public key as it is not stored
+ * during kari initialization.
+ */
+ ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT);
+ 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 +527,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..67b35627ba5e 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-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
@@ -14,20 +14,107 @@
#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_ALLOC_FUNCTIONS(CMS_ContentInfo)
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;
+}
+
+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 +123,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 +147,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 +158,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 +196,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 +210,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 +224,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 +271,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 +284,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 +311,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 +321,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 +339,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 +356,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 +368,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 +386,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);
+ if (mdbio == NULL || BIO_set_md(mdbio, digest) <= 0) {
+ 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 +446,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 +474,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 +490,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 +513,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 +556,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 +572,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);
@@ -469,11 +603,12 @@ int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
{
- int r;
- r = CMS_add0_crl(cms, crl);
- if (r > 0)
- X509_CRL_up_ref(crl);
- return r;
+ if (!X509_CRL_up_ref(crl))
+ return 0;
+ if (CMS_add0_crl(cms, crl))
+ return 1;
+ X509_CRL_free(crl);
+ return 0;
}
STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
@@ -482,22 +617,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 +641,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 +663,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 +681,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 +689,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..1e0e0910d1d1 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-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,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;
@@ -342,6 +368,7 @@ struct CMS_Receipt_st {
DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
DECLARE_ASN1_ITEM(CMS_SignerInfo)
+DECLARE_ASN1_ITEM(CMS_EncryptedContentInfo)
DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber)
DECLARE_ASN1_ITEM(CMS_Attributes_Sign)
DECLARE_ASN1_ITEM(CMS_Attributes_Verify)
@@ -362,66 +389,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..d5c3c8d399df 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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();
@@ -144,21 +157,22 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
/* Setup PBE algorithm */
- pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
+ pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set_ex(iter, NULL, 0, -1, -1,
+ cms_ctx->libctx);
- 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 +191,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 +203,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 +244,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 +272,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 +288,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 +321,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;
}
@@ -336,10 +352,11 @@ int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
/* Finish password based key derivation to setup key in "ctx" */
- 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);
+ if (EVP_PBE_CipherInit_ex(algtmp->algorithm,
+ (char *)pwri->pass, pwri->passlen,
+ algtmp->parameter, kekctx, en_de,
+ cms_ctx->libctx, cms_ctx->propq) < 0) {
+ ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
goto err;
}
@@ -347,7 +364,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 +372,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 +380,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 +399,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..5e26e89d5012
--- /dev/null
+++ b/crypto/cms/cms_rsa.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2006-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/cms.h>
+#include <openssl/err.h>
+#include <openssl/core_names.h>
+#include "crypto/asn1.h"
+#include "crypto/rsa.h"
+#include "crypto/evp.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) {
+ OPENSSL_free(label);
+ 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;
+ ASN1_OCTET_STRING *los = 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)
+ return X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption),
+ V_ASN1_NULL, NULL);
+
+ /* 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) {
+ 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))
+ goto err;
+
+ if (!X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
+ V_ASN1_OCTET_STRING, los))
+ goto err;
+
+ los = NULL;
+ }
+ /* create string with oaep parameter encoding. */
+ if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os))
+ goto err;
+ if (!X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os))
+ goto err;
+ os = NULL;
+ rv = 1;
+ err:
+ RSA_OAEP_PARAMS_free(oaep);
+ ASN1_STRING_free(os);
+ ASN1_OCTET_STRING_free(los);
+ 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;
+
+ if (evp_pkey_ctx_is_legacy(pkctx)) {
+ /* No provider -> we cannot query it for algorithm ID. */
+ ASN1_STRING *os = NULL;
+
+ os = ossl_rsa_ctx_to_pss_string(pkctx);
+ if (os == NULL)
+ return 0;
+ if (X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os))
+ return 1;
+ ASN1_STRING_free(os);
+ 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..4758d048386e 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-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
@@ -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) > 0;
+ else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS"))
+ return ossl_cms_rsa_sign(si, cmd) > 0;
+
+ /* 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,22 +349,32 @@ 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) {
int def_nid;
- if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
+
+ if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) {
+ ERR_raise_data(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST,
+ "pkey nid=%d", EVP_PKEY_get_id(pk));
goto err;
+ }
md = EVP_get_digestbynid(def_nid);
if (md == NULL) {
- CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST);
+ ERR_raise_data(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST,
+ "default md nid=%d", def_nid);
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 +383,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;
}
@@ -324,8 +403,11 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
}
}
- if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0))
+ if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0)) {
+ ERR_raise_data(ERR_LIB_CMS, CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM,
+ "pkey nid=%d", EVP_PKEY_get_id(pk));
goto err;
+ }
if (!(flags & CMS_NOATTR)) {
/*
* Initialize signed attributes structure so other attributes
@@ -346,6 +428,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 +468,26 @@ 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) {
+ si->pctx = NULL;
goto err;
+ }
+ else {
+ EVP_MD_CTX_set_flags(si->mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+ }
}
if (!sd->signerInfos)
@@ -385,23 +498,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 +541,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 +564,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 +575,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 +592,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 +605,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 +623,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 +642,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 +664,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 +685,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 +710,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 +727,15 @@ 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;
+ si->pctx = NULL;
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 +746,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 +771,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 +794,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 +806,22 @@ 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;
+ EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
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 +837,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,33 +854,59 @@ 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 (si->pctx != NULL) {
+ EVP_PKEY_CTX_free(si->pctx);
+ si->pctx = NULL;
+ }
+ if (EVP_DigestVerifyInit_ex(mctx, &si->pctx, EVP_MD_get0_name(md), libctx,
+ propq, si->pkey, NULL) <= 0) {
+ si->pctx = NULL;
goto err;
+ }
+ EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
if (!cms_sd_asn1_ctrl(si, 1))
goto err;
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 +917,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 +967,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 +975,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)
@@ -859,13 +1016,15 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0)
goto err;
si->pctx = pkctx;
- if (!cms_sd_asn1_ctrl(si, 1))
+ if (!cms_sd_asn1_ctrl(si, 1)) {
+ si->pctx = NULL;
goto err;
+ }
+ si->pctx = NULL;
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 +1040,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;
@@ -893,30 +1053,32 @@ 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)
{
- X509_ALGOR *alg;
+ X509_ALGOR *alg = NULL;
ASN1_INTEGER *key = NULL;
+
if (keysize > 0) {
key = ASN1_INTEGER_new();
- if (key == NULL || !ASN1_INTEGER_set(key, keysize)) {
- ASN1_INTEGER_free(key);
- return 0;
- }
+ if (key == NULL || !ASN1_INTEGER_set(key, keysize))
+ goto err;
}
alg = X509_ALGOR_new();
- if (alg == NULL) {
- ASN1_INTEGER_free(key);
- return 0;
- }
+ if (alg == NULL)
+ goto err;
- X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
- key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key);
+ if (!X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
+ key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key))
+ goto err;
+ key = NULL;
if (*algs == NULL)
*algs = sk_X509_ALGOR_new_null();
- if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg)) {
- X509_ALGOR_free(alg);
- return 0;
- }
+ if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg))
+ goto err;
return 1;
+
+ err:
+ ASN1_INTEGER_free(key);
+ X509_ALGOR_free(alg);
+ return 0;
}
/* Check to see if a cipher exists and if so add S/MIME capabilities */
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
index 6e7dbc4da1fa..65da2452fcea 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-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,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,45 +189,54 @@ 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))
- return NULL;
+ goto err;
if (!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
@@ -220,42 +245,57 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
|| CMS_final(cms, in, NULL, flags))
return cms;
+ err:
CMS_ContentInfo_free(cms);
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 +309,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 +330,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 +345,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 +399,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 +422,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 +455,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 +478,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 +494,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 +518,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,35 +540,44 @@ 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)
{
CMS_SignerInfo *rct_si;
CMS_ContentInfo *cms = NULL;
- ASN1_OCTET_STRING **pos, *os;
+ ASN1_OCTET_STRING **pos, *os = NULL;
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 +586,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 +610,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;
@@ -539,23 +621,29 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
if (r)
return cms;
CMS_ContentInfo_free(cms);
+ ASN1_OCTET_STRING_free(os);
return NULL;
}
-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 +658,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,42 +697,56 @@ 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)
{
- STACK_OF(CMS_RecipientInfo) *ris;
+ 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_get0_RecipientInfos(cms);
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;
+ CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
+
+ /* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
+ if (ec != NULL) {
+ OPENSSL_clear_free(ec->key, ec->keylen);
+ ec->key = NULL;
+ ec->keylen = 0;
+ }
+
+ if (ris != NULL && ec != NULL)
+ debug = ec->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)
return 0;
}
- /*
- * If we have a cert try matching RecipientInfo otherwise try them
- * all.
- */
- else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
+ /* If we have a cert, try matching RecipientInfo, else try them all */
+ 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 +757,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 +765,21 @@ 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);
+ if (!match_ri)
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
@@ -675,32 +790,33 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
{
STACK_OF(CMS_RecipientInfo) *ris;
CMS_RecipientInfo *ri;
- int i, r;
+ int i, r, match_ri = 0;
+
ris = CMS_get0_RecipientInfos(cms);
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
ri = sk_CMS_RecipientInfo_value(ris, i);
if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
continue;
- /*
- * If we have an id try matching RecipientInfo otherwise try them
- * all.
- */
- if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
+ /* If we have an id, try matching RecipientInfo, else try them all */
+ if (id == NULL
+ || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
+ match_ri = 1;
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);
+ if (!match_ri)
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
@@ -708,14 +824,25 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
unsigned char *pass, ossl_ssize_t passlen)
{
- STACK_OF(CMS_RecipientInfo) *ris;
+ STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
CMS_RecipientInfo *ri;
- int i, r;
- ris = CMS_get0_RecipientInfos(cms);
+ int i, r, match_ri = 0;
+ CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
+
+ /* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
+ if (ec != NULL) {
+ OPENSSL_clear_free(ec->key, ec->keylen);
+ ec->key = NULL;
+ ec->keylen = 0;
+ }
+
for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
ri = sk_CMS_RecipientInfo_value(ris, i);
if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
continue;
+
+ /* Must try each PasswordRecipientInfo */
+ match_ri = 1;
CMS_RecipientInfo_set0_password(ri, pass, passlen);
r = CMS_RecipientInfo_decrypt(cms, ri);
CMS_RecipientInfo_set0_password(ri, NULL, 0);
@@ -723,7 +850,8 @@ int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
return 1;
}
- CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
+ if (!match_ri)
+ ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
return 0;
}
@@ -733,26 +861,25 @@ 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);
+ CMS_EncryptedContentInfo *ec;
+ 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;
- else
- cms->d.envelopedData->encryptedContentInfo->debug = 0;
- if (!cert)
- cms->d.envelopedData->encryptedContentInfo->havenocert = 1;
- else
- cms->d.envelopedData->encryptedContentInfo->havenocert = 0;
- if (!pk && !cert && !dcont && !out)
+ ec = ossl_cms_get0_env_enc_content(cms);
+ ec->debug = (flags & CMS_DEBUG_DECRYPT) != 0;
+ ec->havenocert = cert == NULL;
+ 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 +892,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 +923,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 +943,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 +965,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..cda2f3e26792 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 */
@@ -198,26 +226,29 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
char *dirpath = NULL;
OPENSSL_DIR_CTX *dirctx = NULL;
#endif
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ int numincludes = 0;
+#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 +256,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 +280,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
@@ -300,7 +332,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
v = NULL;
/* check for line continuation */
- if (bufnum >= 1) {
+ if (!again && bufnum >= 1) {
/*
* If we have bytes and the last char '\\' and second last char
* is not '\\'
@@ -334,8 +366,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 +375,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 +392,75 @@ 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;
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /*
+ * The include processing below can cause the "conf" fuzzer to
+ * timeout due to the fuzzer inserting large and complicated
+ * includes - with a large amount of time spent in
+ * OPENSSL_strlcat/OPENSSL_strcpy. This is not a security
+ * concern because config files should never come from untrusted
+ * sources. We just set an arbitrary limit on the allowed
+ * number of includes when fuzzing to prevent this timeout.
+ */
+ if (numincludes++ > 10)
+ goto err;
+#endif
+
+ if (include_dir == NULL)
+ include_dir = conf->includedir;
if (*p == '=') {
p++;
@@ -374,28 +469,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 +527,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 +537,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 +554,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 +575,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 +706,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 +726,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 +736,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 +745,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 +765,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 +815,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 +856,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 +867,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 +952,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..fc0eee7d2f85 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,13 @@ 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_RECURSIVE_SECTION_REFERENCE),
+ "recursive section reference"},
+ {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 +64,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..719af7cb75c6 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
}
@@ -410,6 +464,9 @@ int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings,
void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings)
{
+ if (settings == NULL)
+ return;
+
free(settings->filename);
free(settings->appname);
free(settings);
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..1ea32648e9f9 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-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 "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,122 @@ 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;
+
+ ERR_set_mark();
if (filename == NULL) {
file = CONF_get1_default_config_file();
- if (!file)
+ if (file == NULL)
goto err;
- } else
+ if (*file == '\0') {
+ /* Do not try to load an empty file name but do not error out */
+ ret = 1;
+ goto err;
+ }
+ } else {
file = (char *)filename;
+ }
+
+ 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 +263,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 +272,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 +291,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 +311,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 +327,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)) {
+ if (!sk_CONF_MODULE_push(supported_modules, tmod))
+ goto err;
+
+ 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 +383,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 +431,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 +484,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 +501,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 +520,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 +574,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 +628,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 +666,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 +677,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..106434dcbf3d 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
@@ -37,42 +38,45 @@ void OPENSSL_config(const char *appname)
settings.appname = strdup(appname);
settings.flags = DEFAULT_CONF_MFLAGS;
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, &settings);
+
+ free(settings.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);
+ ret = CONF_modules_load_file_ex(OSSL_LIB_CTX_get0_global_default(),
+ filename, appname, flags);
+#else
+ ret = 1;
#endif
openssl_configured = 1;
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..ac6938e619eb
--- /dev/null
+++ b/crypto/context.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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 (ctx == NULL || 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..c063515fc04d
--- /dev/null
+++ b/crypto/core_fetch.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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(no_store ? data->store : NULL,
+ 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..ebf7ed5eb165
--- /dev/null
+++ b/crypto/core_namemap.c
@@ -0,0 +1,534 @@
+/*
+ * 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/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;
+
+ if (namemap == NULL)
+ return 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..e20eb62081c5 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-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
*/
+/*
+ * 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,53 @@ 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)
{
- int ok = 0, r;
+#ifdef FIPS_MODULE
+ return DH_check_params(dh, ret);
+#else
+ int ok = 0, r, q_good = 0;
BN_CTX *ctx = NULL;
BIGNUM *t1 = NULL, *t2 = NULL;
+ int nid = DH_get_nid((DH *)dh);
+
+ *ret = 0;
+ if (nid != NID_undef)
+ return 1;
+
+ /* Don't do any checks at all with an excessively large modulus */
+ if (BN_num_bits(dh->params.p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
+ *ret = DH_MODULUS_TOO_LARGE | DH_CHECK_P_NOT_PRIME;
+ return 0;
+ }
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 +171,49 @@ 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_ucmp(dh->params.p, dh->params.q) > 0)
+ q_good = 1;
+ else
+ *ret |= DH_CHECK_INVALID_Q_VALUE;
+ }
+
+ if (q_good) {
+ 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 +224,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 +235,126 @@ 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)
{
+ /* Don't do any checks at all with an excessively large modulus */
+ if (BN_num_bits(dh->params.p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
+ *ret = DH_MODULUS_TOO_LARGE | DH_CHECK_PUBKEY_INVALID;
+ return 0;
+ }
+
+ if (dh->params.q != NULL && BN_ucmp(dh->params.p, dh->params.q) < 0) {
+ *ret |= DH_CHECK_INVALID_Q_VALUE | DH_CHECK_PUBKEY_INVALID;
+ return 1;
+ }
+
+ 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)
+ && *ret == 0;
+}
+
+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..f76ac0dd1463 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-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,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"},
@@ -81,21 +54,23 @@ static const ERR_STRING_DATA DH_str_reasons[] = {
{ERR_PACK(ERR_LIB_DH, 0, DH_R_PARAMETER_ENCODING_ERROR),
"parameter encoding error"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_PEER_KEY_ERROR), "peer key error"},
+ {ERR_PACK(ERR_LIB_DH, 0, DH_R_Q_TOO_LARGE), "q too large"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_SHARED_INFO_ERROR), "shared info error"},
{ERR_PACK(ERR_LIB_DH, 0, DH_R_UNABLE_TO_CHECK_GENERATOR),
"unable to check generator"},
{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..afc49f5cdc87 100644
--- a/crypto/dh/dh_key.c
+++ b/crypto/dh/dh_key.c
@@ -1,28 +1,110 @@
/*
- * Copyright 1995-2021 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
*/
+/*
+ * 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 (dh->params.q != NULL
+ && BN_num_bits(dh->params.q) > OPENSSL_DH_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_Q_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 +117,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 +146,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 +165,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 +181,110 @@ 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;
+ 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 (dh->params.q != NULL
+ && BN_num_bits(dh->params.q) > OPENSSL_DH_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DH, DH_R_Q_TOO_LARGE);
+ return 0;
+ }
+
+ 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 +293,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 +381,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;
+ int err_reason = DH_R_BN_ERROR;
+ BIGNUM *pubkey = NULL;
+ const BIGNUM *p;
+ int ret;
- if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
- DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
+ if ((pubkey = BN_bin2bn(buf, len, NULL)) == NULL)
goto err;
- }
-
- ctx = BN_CTX_new();
- if (ctx == NULL)
- goto err;
- BN_CTX_start(ctx);
- tmp = BN_CTX_get(ctx);
- if (tmp == 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..5577413e1e0c 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-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
*/
+/*
+ * 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,15 @@ 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 */
+
+ ossl_ffc_params_init(&ret->params);
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 +145,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 +172,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 +248,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 +271,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 +315,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..fd6c85230236 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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);
- if (ret < 0)
+ 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..389df304bdce
--- /dev/null
+++ b/crypto/dsa/dsa_backend.c
@@ -0,0 +1,195 @@
+/*
+ * 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
+ */
+
+/*
+ * 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;
+ }
+ if (!DSA_set0_key(dsa, dsa_pubkey, dsa_privkey)) {
+ ERR_raise(ERR_LIB_DSA, ERR_R_INTERNAL_ERROR);
+ goto dsaerr;
+ }
+
+ 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..801b932d8724
--- /dev/null
+++ b/crypto/dsa/dsa_check.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with 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"
+
+static int dsa_precheck_params(const DSA *dsa, int *ret)
+{
+ if (dsa->params.p == NULL || dsa->params.q == NULL) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS);
+ *ret = FFC_CHECK_INVALID_PQ;
+ return 0;
+ }
+
+ if (BN_num_bits(dsa->params.p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_MODULUS_TOO_LARGE);
+ *ret = FFC_CHECK_INVALID_PQ;
+ return 0;
+ }
+
+ if (BN_num_bits(dsa->params.q) >= BN_num_bits(dsa->params.p)) {
+ ERR_raise(ERR_LIB_DSA, DSA_R_BAD_Q_VALUE);
+ *ret = FFC_CHECK_INVALID_PQ;
+ return 0;
+ }
+
+ return 1;
+}
+
+int ossl_dsa_check_params(const DSA *dsa, int checktype, int *ret)
+{
+ if (!dsa_precheck_params(dsa, ret))
+ return 0;
+
+ 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)
+{
+ if (!dsa_precheck_params(dsa, ret))
+ return 0;
+
+ return ossl_ffc_validate_public_key(&dsa->params, pub_key, ret)
+ && *ret == 0;
+}
+
+/*
+ * 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)
+{
+ if (!dsa_precheck_params(dsa, ret))
+ return 0;
+
+ return ossl_ffc_validate_public_key_partial(&dsa->params, pub_key, ret)
+ && *ret == 0;
+}
+
+int ossl_dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret)
+{
+ *ret = 0;
+
+ if (!dsa_precheck_params(dsa, ret))
+ return 0;
+
+ return 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_precheck_params(dsa, &ret))
+ return 0;
+
+ if (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..a92ca6166477 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-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,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,24 @@ 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"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_TOO_MANY_RETRIES), "too many retries"},
{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..2ae3f8e36b26 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-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>
+/*
+ * 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,16 @@ 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
+
+ ossl_ffc_params_init(&ret->params);
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 +190,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 +222,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 +250,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 +313,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 +321,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..0c18b78f7633 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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"
@@ -15,6 +21,9 @@
#include "dsa_local.h"
#include <openssl/asn1.h>
+#define MIN_DSA_SIGN_QBITS 128
+#define MAX_DSA_SIGN_RETRIES 8
+
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp);
@@ -44,10 +53,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 +70,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;
@@ -67,8 +78,11 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
int reason = ERR_R_BN_LIB;
DSA_SIG *ret = NULL;
int rv = 0;
+ int retries = 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 +99,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 +113,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;
@@ -119,10 +133,13 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
* s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod q
*/
- /* Generate a blinding value */
+ /*
+ * Generate a blinding value
+ * The size of q is tested in dsa_sign_setup() so there should not be an infinite loop here.
+ */
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,41 +147,46 @@ 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;
/*
- * Redo if r or s is zero as required by FIPS 186-3: this is very
- * unlikely.
+ * Redo if r or s is zero as required by FIPS 186-4: Section 4.6
+ * This is very unlikely.
+ * Limit the retries so there is no possibility of an infinite
+ * loop for bad domain parameter values.
*/
- if (BN_is_zero(ret->r) || BN_is_zero(ret->s))
+ if (BN_is_zero(ret->r) || BN_is_zero(ret->s)) {
+ if (retries++ > MAX_DSA_SIGN_RETRIES) {
+ reason = DSA_R_TOO_MANY_RETRIES;
+ goto err;
+ }
goto redo;
-
+ }
rv = 1;
-
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 +195,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,36 +216,42 @@ 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)
+ || BN_is_negative(dsa->params.p)
+ || BN_is_negative(dsa->params.q)
+ || BN_is_negative(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;
}
-
k = BN_new();
l = BN_new();
if (k == NULL || l == NULL)
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);
- if (!bn_wexpand(k, q_words + 2)
+ q_bits = BN_num_bits(dsa->params.q);
+ q_words = bn_get_top(dsa->params.q);
+ if (q_bits < MIN_DSA_SIGN_QBITS
+ || !bn_wexpand(k, q_words + 2)
|| !bn_wexpand(l, q_words + 2))
goto err;
@@ -229,19 +262,20 @@ 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,
- dlen, ctx))
+ if (!ossl_bn_gen_dsa_nonce_fixed_top(k, dsa->params.q,
+ dsa->priv_key, dgst,
+ dlen, ctx))
goto err;
- } else if (!BN_priv_rand_range(k, dsa->q))
+ } else if (!ossl_bn_priv_rand_range_fixed_top(k, dsa->params.q, 0, ctx))
goto err;
- } while (BN_is_zero(k));
+ } while (ossl_bn_is_word_fixed_top(k, 0));
BN_set_flags(k, BN_FLG_CONSTTIME);
BN_set_flags(l, BN_FLG_CONSTTIME);
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 +294,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 +323,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 +339,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 +381,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 +396,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 +431,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 +442,7 @@ 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;
+ 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..91d334ea533a 100644
--- a/crypto/dsa/dsa_sign.c
+++ b/crypto/dsa/dsa_sign.c
@@ -1,24 +1,214 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
+
+ if (sig == NULL) {
+ *siglen = DSA_size(dsa);
+ return 1;
+ }
+
+ /* 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..05b63cf1d9c2 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,16 +232,15 @@ 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) {
- if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
- sprintf(translated, "lib%s%s", filename, DSO_EXTENSION);
- else
- sprintf(translated, "%s%s", filename, DSO_EXTENSION);
- } else
- sprintf(translated, "%s", filename);
+ if (transform)
+ BIO_snprintf(translated, rsize,
+ (DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0
+ ? "lib%s%s" : "%s%s", filename, DSO_EXTENSION);
+ else
+ BIO_snprintf(translated, rsize, "%s", filename);
return translated;
}
diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c
index 4719e8f4f337..1107da5fe657 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,16 +266,17 @@ 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) {
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
- sprintf(translated, "lib%s" DSO_EXTENSION, filename);
+ BIO_snprintf(translated, rsize, "lib%s" DSO_EXTENSION, filename);
else
- sprintf(translated, "%s" DSO_EXTENSION, filename);
- } else
- sprintf(translated, "%s", filename);
+ BIO_snprintf(translated, rsize, "%s" DSO_EXTENSION, filename);
+ } else {
+ BIO_snprintf(translated, rsize, "%s", filename);
+ }
return translated;
}
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/dso/dso_vms.c b/crypto/dso/dso_vms.c
new file mode 100644
index 000000000000..aa2dfaa4d15f
--- /dev/null
+++ b/crypto/dso/dso_vms.c
@@ -0,0 +1,489 @@
+/*
+ * 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
+ */
+
+#include "dso_local.h"
+
+#ifdef OPENSSL_SYS_VMS
+
+# pragma message disable DOLLARID
+# include <errno.h>
+# include <rms.h>
+# include <lib$routines.h>
+# include <libfisdef.h>
+# include <stsdef.h>
+# include <descrip.h>
+# include <starlet.h>
+# include "../vms_rms.h"
+
+/* Some compiler options may mask the declaration of "_malloc32". */
+# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
+# if __INITIAL_POINTER_SIZE == 64
+# pragma pointer_size save
+# pragma pointer_size 32
+void *_malloc32(__size_t);
+# pragma pointer_size restore
+# endif /* __INITIAL_POINTER_SIZE == 64 */
+# endif /* __INITIAL_POINTER_SIZE && defined
+ * _ANSI_C_SOURCE */
+
+# pragma message disable DOLLARID
+
+static int vms_load(DSO *dso);
+static int vms_unload(DSO *dso);
+static DSO_FUNC_TYPE vms_bind_func(DSO *dso, const char *symname);
+static char *vms_name_converter(DSO *dso, const char *filename);
+static char *vms_merger(DSO *dso, const char *filespec1,
+ const char *filespec2);
+
+static DSO_METHOD dso_meth_vms = {
+ "OpenSSL 'VMS' shared library method",
+ vms_load,
+ NULL, /* unload */
+ vms_bind_func,
+ NULL, /* ctrl */
+ vms_name_converter,
+ vms_merger,
+ NULL, /* init */
+ NULL, /* finish */
+ NULL, /* pathbyaddr */
+ NULL /* globallookup */
+};
+
+/*
+ * On VMS, the only "handle" is the file name. LIB$FIND_IMAGE_SYMBOL depends
+ * on the reference to the file name being the same for all calls regarding
+ * one shared image, so we'll just store it in an instance of the following
+ * structure and put a pointer to that instance in the meth_data stack.
+ */
+typedef struct dso_internal_st {
+ /*
+ * This should contain the name only, no directory, no extension, nothing
+ * but a name.
+ */
+ struct dsc$descriptor_s filename_dsc;
+ char filename[NAMX_MAXRSS + 1];
+ /*
+ * This contains whatever is not in filename, if needed. Normally not
+ * defined.
+ */
+ struct dsc$descriptor_s imagename_dsc;
+ char imagename[NAMX_MAXRSS + 1];
+} DSO_VMS_INTERNAL;
+
+DSO_METHOD *DSO_METHOD_openssl(void)
+{
+ return &dso_meth_vms;
+}
+
+static int vms_load(DSO *dso)
+{
+ void *ptr = NULL;
+ /* See applicable comments in dso_dl.c */
+ char *filename = DSO_convert_filename(dso, NULL);
+
+/* Ensure 32-bit pointer for "p", and appropriate malloc() function. */
+# if __INITIAL_POINTER_SIZE == 64
+# define DSO_MALLOC _malloc32
+# pragma pointer_size save
+# pragma pointer_size 32
+# else /* __INITIAL_POINTER_SIZE == 64 */
+# define DSO_MALLOC OPENSSL_malloc
+# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+
+ DSO_VMS_INTERNAL *p = NULL;
+
+# if __INITIAL_POINTER_SIZE == 64
+# pragma pointer_size restore
+# endif /* __INITIAL_POINTER_SIZE == 64 */
+
+ const char *sp1, *sp2; /* Search result */
+ const char *ext = NULL; /* possible extension to add */
+
+ if (filename == NULL) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
+ goto err;
+ }
+
+ /*-
+ * A file specification may look like this:
+ *
+ * node::dev:[dir-spec]name.type;ver
+ *
+ * or (for compatibility with TOPS-20):
+ *
+ * node::dev:<dir-spec>name.type;ver
+ *
+ * and the dir-spec uses '.' as separator. Also, a dir-spec
+ * may consist of several parts, with mixed use of [] and <>:
+ *
+ * [dir1.]<dir2>
+ *
+ * We need to split the file specification into the name and
+ * the rest (both before and after the name itself).
+ */
+ /*
+ * Start with trying to find the end of a dir-spec, and save the position
+ * of the byte after in sp1
+ */
+ sp1 = strrchr(filename, ']');
+ sp2 = strrchr(filename, '>');
+ if (sp1 == NULL)
+ sp1 = sp2;
+ if (sp2 != NULL && sp2 > sp1)
+ sp1 = sp2;
+ if (sp1 == NULL)
+ sp1 = strrchr(filename, ':');
+ if (sp1 == NULL)
+ sp1 = filename;
+ else
+ sp1++; /* The byte after the found character */
+ /* Now, let's see if there's a type, and save the position in sp2 */
+ sp2 = strchr(sp1, '.');
+ /*
+ * If there is a period and the next character is a semi-colon,
+ * we need to add an extension
+ */
+ if (sp2 != NULL && sp2[1] == ';')
+ ext = ".EXE";
+ /*
+ * If we found it, that's where we'll cut. Otherwise, look for a version
+ * number and save the position in sp2
+ */
+ if (sp2 == NULL) {
+ sp2 = strchr(sp1, ';');
+ ext = ".EXE";
+ }
+ /*
+ * If there was still nothing to find, set sp2 to point at the end of the
+ * string
+ */
+ if (sp2 == NULL)
+ sp2 = sp1 + strlen(sp1);
+
+ /* Check that we won't get buffer overflows */
+ if (sp2 - sp1 > FILENAME_MAX
+ || (sp1 - filename) + strlen(sp2) > FILENAME_MAX) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_FILENAME_TOO_BIG);
+ goto err;
+ }
+
+ p = DSO_MALLOC(sizeof(*p));
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ strncpy(p->filename, sp1, sp2 - sp1);
+ p->filename[sp2 - sp1] = '\0';
+
+ strncpy(p->imagename, filename, sp1 - filename);
+ p->imagename[sp1 - filename] = '\0';
+ if (ext) {
+ strcat(p->imagename, ext);
+ if (*sp2 == '.')
+ sp2++;
+ }
+ strcat(p->imagename, sp2);
+
+ p->filename_dsc.dsc$w_length = strlen(p->filename);
+ p->filename_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ p->filename_dsc.dsc$b_class = DSC$K_CLASS_S;
+ p->filename_dsc.dsc$a_pointer = p->filename;
+ p->imagename_dsc.dsc$w_length = strlen(p->imagename);
+ p->imagename_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ p->imagename_dsc.dsc$b_class = DSC$K_CLASS_S;
+ p->imagename_dsc.dsc$a_pointer = p->imagename;
+
+ if (!sk_void_push(dso->meth_data, (char *)p)) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
+ goto err;
+ }
+
+ /* Success (for now, we lie. We actually do not know...) */
+ dso->loaded_filename = filename;
+ return 1;
+ err:
+ /* Cleanup! */
+ OPENSSL_free(p);
+ OPENSSL_free(filename);
+ return 0;
+}
+
+/*
+ * Note that this doesn't actually unload the shared image, as there is no
+ * such thing in VMS. Next time it get loaded again, a new copy will
+ * actually be loaded.
+ */
+static int vms_unload(DSO *dso)
+{
+ DSO_VMS_INTERNAL *p;
+ if (dso == NULL) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (sk_void_num(dso->meth_data) < 1)
+ return 1;
+ p = (DSO_VMS_INTERNAL *)sk_void_pop(dso->meth_data);
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
+ return 0;
+ }
+ /* Cleanup */
+ OPENSSL_free(p);
+ return 1;
+}
+
+/*
+ * We must do this in a separate function because of the way the exception
+ * handler works (it makes this function return
+ */
+static int do_find_symbol(DSO_VMS_INTERNAL *ptr,
+ struct dsc$descriptor_s *symname_dsc, void **sym,
+ unsigned long flags)
+{
+ /*
+ * Make sure that signals are caught and returned instead of aborting the
+ * program. The exception handler gets unestablished automatically on
+ * return from this function.
+ */
+ lib$establish(lib$sig_to_ret);
+
+ if (ptr->imagename_dsc.dsc$w_length)
+ return lib$find_image_symbol(&ptr->filename_dsc,
+ symname_dsc, sym,
+ &ptr->imagename_dsc, flags);
+ else
+ return lib$find_image_symbol(&ptr->filename_dsc,
+ symname_dsc, sym, 0, flags);
+}
+
+# ifndef LIB$M_FIS_MIXEDCASE
+# define LIB$M_FIS_MIXEDCASE (1 << 4);
+# endif
+void vms_bind_sym(DSO *dso, const char *symname, void **sym)
+{
+ DSO_VMS_INTERNAL *ptr;
+ int status = 0;
+ struct dsc$descriptor_s symname_dsc;
+
+/* Arrange 32-bit pointer to (copied) string storage, if needed. */
+# if __INITIAL_POINTER_SIZE == 64
+# define SYMNAME symname_32p
+# pragma pointer_size save
+# pragma pointer_size 32
+ char *symname_32p;
+# pragma pointer_size restore
+ char symname_32[NAMX_MAXRSS + 1];
+# else /* __INITIAL_POINTER_SIZE == 64 */
+# define SYMNAME ((char *) symname)
+# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+
+ *sym = NULL;
+
+ if ((dso == NULL) || (symname == NULL)) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
+ return;
+ }
+# if __INITIAL_POINTER_SIZE == 64
+ /* Copy the symbol name to storage with a 32-bit pointer. */
+ symname_32p = symname_32;
+ strcpy(symname_32p, symname);
+# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+
+ symname_dsc.dsc$w_length = strlen(SYMNAME);
+ symname_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ symname_dsc.dsc$b_class = DSC$K_CLASS_S;
+ symname_dsc.dsc$a_pointer = SYMNAME;
+
+ if (sk_void_num(dso->meth_data) < 1) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
+ return;
+ }
+ ptr = (DSO_VMS_INTERNAL *)sk_void_value(dso->meth_data,
+ sk_void_num(dso->meth_data) - 1);
+ if (ptr == NULL) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
+ return;
+ }
+
+ status = do_find_symbol(ptr, &symname_dsc, sym, LIB$M_FIS_MIXEDCASE);
+
+ if (!$VMS_STATUS_SUCCESS(status))
+ status = do_find_symbol(ptr, &symname_dsc, sym, 0);
+
+ if (!$VMS_STATUS_SUCCESS(status)) {
+ unsigned short length;
+ char errstring[257];
+ struct dsc$descriptor_s errstring_dsc;
+
+ errstring_dsc.dsc$w_length = sizeof(errstring);
+ errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ errstring_dsc.dsc$b_class = DSC$K_CLASS_S;
+ errstring_dsc.dsc$a_pointer = errstring;
+
+ *sym = NULL;
+
+ status = sys$getmsg(status, &length, &errstring_dsc, 1, 0);
+
+ if (!$VMS_STATUS_SUCCESS(status))
+ lib$signal(status); /* This is really bad. Abort! */
+ else {
+ errstring[length] = '\0';
+
+ if (ptr->imagename_dsc.dsc$w_length)
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE,
+ "Symbol %s in %s (%s): %s",
+ symname, ptr->filename, ptr->imagename,
+ errstring);
+ else
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE,
+ "Symbol %s in %s: %s",
+ symname, ptr->filename, errstring);
+ }
+ return;
+ }
+ return;
+}
+
+static DSO_FUNC_TYPE vms_bind_func(DSO *dso, const char *symname)
+{
+ DSO_FUNC_TYPE sym = 0;
+ vms_bind_sym(dso, symname, (void **)&sym);
+ return sym;
+}
+
+static char *vms_merger(DSO *dso, const char *filespec1,
+ const char *filespec2)
+{
+ int status;
+ int filespec1len, filespec2len;
+ struct FAB fab;
+ struct NAMX_STRUCT nam;
+ char esa[NAMX_MAXRSS + 1];
+ char *merged;
+
+/* Arrange 32-bit pointer to (copied) string storage, if needed. */
+# if __INITIAL_POINTER_SIZE == 64
+# define FILESPEC1 filespec1_32p;
+# define FILESPEC2 filespec2_32p;
+# pragma pointer_size save
+# pragma pointer_size 32
+ char *filespec1_32p;
+ char *filespec2_32p;
+# pragma pointer_size restore
+ char filespec1_32[NAMX_MAXRSS + 1];
+ char filespec2_32[NAMX_MAXRSS + 1];
+# else /* __INITIAL_POINTER_SIZE == 64 */
+# define FILESPEC1 ((char *) filespec1)
+# define FILESPEC2 ((char *) filespec2)
+# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+
+ if (!filespec1)
+ filespec1 = "";
+ if (!filespec2)
+ filespec2 = "";
+ filespec1len = strlen(filespec1);
+ filespec2len = strlen(filespec2);
+
+# if __INITIAL_POINTER_SIZE == 64
+ /* Copy the file names to storage with a 32-bit pointer. */
+ filespec1_32p = filespec1_32;
+ filespec2_32p = filespec2_32;
+ strcpy(filespec1_32p, filespec1);
+ strcpy(filespec2_32p, filespec2);
+# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+
+ fab = cc$rms_fab;
+ nam = CC_RMS_NAMX;
+
+ FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = FILESPEC1;
+ FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = filespec1len;
+ FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = FILESPEC2;
+ FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = filespec2len;
+ NAMX_DNA_FNA_SET(fab)
+
+ nam.NAMX_ESA = esa;
+ nam.NAMX_ESS = NAMX_MAXRSS;
+ nam.NAMX_NOP = NAM$M_SYNCHK | NAM$M_PWD;
+ SET_NAMX_NO_SHORT_UPCASE(nam);
+
+ fab.FAB_NAMX = &nam;
+
+ status = sys$parse(&fab, 0, 0);
+
+ if (!$VMS_STATUS_SUCCESS(status)) {
+ unsigned short length;
+ char errstring[257];
+ struct dsc$descriptor_s errstring_dsc;
+
+ errstring_dsc.dsc$w_length = sizeof(errstring);
+ errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ errstring_dsc.dsc$b_class = DSC$K_CLASS_S;
+ errstring_dsc.dsc$a_pointer = errstring;
+
+ status = sys$getmsg(status, &length, &errstring_dsc, 1, 0);
+
+ if (!$VMS_STATUS_SUCCESS(status))
+ lib$signal(status); /* This is really bad. Abort! */
+ else {
+ errstring[length] = '\0';
+
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_FAILURE,
+ "filespec \"%s\", default \"%s\": %s",
+ filespec1, filespec2, errstring);
+ }
+ return NULL;
+ }
+
+ merged = OPENSSL_malloc(nam.NAMX_ESL + 1);
+ if (merged == NULL)
+ goto malloc_err;
+ strncpy(merged, nam.NAMX_ESA, nam.NAMX_ESL);
+ merged[nam.NAMX_ESL] = '\0';
+ return merged;
+ malloc_err:
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+}
+
+static char *vms_name_converter(DSO *dso, const char *filename)
+{
+ char *translated;
+ int len, transform;
+ const char *p;
+
+ len = strlen(filename);
+
+ p = strchr(filename, ':');
+ if (p != NULL) {
+ transform = 0;
+ } else {
+ p = filename;
+ transform = (strrchr(p, '>') == NULL && strrchr(p, ']') == NULL);
+ }
+
+ if (transform) {
+ int rsize = len + sizeof(DSO_EXTENSION);
+
+ if ((translated = OPENSSL_malloc(rsize)) != NULL) {
+ p = strrchr(filename, ';');
+ if (p != NULL)
+ len = p - filename;
+ strncpy(translated, filename, len);
+ translated[len] = '\0';
+ strcat(translated, DSO_EXTENSION);
+ if (p != NULL)
+ strcat(translated, p);
+ }
+ } else {
+ translated = OPENSSL_strdup(filename);
+ }
+ return translated;
+}
+
+#endif /* OPENSSL_SYS_VMS */
diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c
new file mode 100644
index 000000000000..91a1a9d9aeb5
--- /dev/null
+++ b/crypto/dso/dso_win32.c
@@ -0,0 +1,667 @@
+/*
+ * 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "e_os.h"
+#include "dso_local.h"
+
+#if defined(DSO_WIN32)
+
+# ifdef _WIN32_WCE
+# if _WIN32_WCE < 300
+static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName)
+{
+ WCHAR lpProcNameW[64];
+ int i;
+
+ for (i = 0; lpProcName[i] && i < 64; i++)
+ lpProcNameW[i] = (WCHAR)lpProcName[i];
+ if (i == 64)
+ return NULL;
+ lpProcNameW[i] = 0;
+
+ return GetProcAddressW(hModule, lpProcNameW);
+}
+# endif
+# undef GetProcAddress
+# define GetProcAddress GetProcAddressA
+
+static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName)
+{
+ WCHAR *fnamw;
+ size_t len_0 = strlen(lpLibFileName) + 1, i;
+
+# ifdef _MSC_VER
+ fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR));
+# else
+ fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
+# endif
+ if (fnamw == NULL) {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+# if defined(_WIN32_WCE) && _WIN32_WCE>=101
+ if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0))
+# endif
+ for (i = 0; i < len_0; i++)
+ fnamw[i] = (WCHAR)lpLibFileName[i];
+
+ return LoadLibraryW(fnamw);
+}
+# endif
+
+/* Part of the hack in "win32_load" ... */
+# define DSO_MAX_TRANSLATED_SIZE 256
+
+static int win32_load(DSO *dso);
+static int win32_unload(DSO *dso);
+static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
+static char *win32_name_converter(DSO *dso, const char *filename);
+static char *win32_merger(DSO *dso, const char *filespec1,
+ const char *filespec2);
+static int win32_pathbyaddr(void *addr, char *path, int sz);
+static void *win32_globallookup(const char *name);
+
+static const char *openssl_strnchr(const char *string, int c, size_t len);
+
+static DSO_METHOD dso_meth_win32 = {
+ "OpenSSL 'win32' shared library method",
+ win32_load,
+ win32_unload,
+ win32_bind_func,
+ NULL, /* ctrl */
+ win32_name_converter,
+ win32_merger,
+ NULL, /* init */
+ NULL, /* finish */
+ win32_pathbyaddr, /* pathbyaddr */
+ win32_globallookup
+};
+
+DSO_METHOD *DSO_METHOD_openssl(void)
+{
+ return &dso_meth_win32;
+}
+
+/*
+ * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
+ * the handle (HINSTANCE) returned from LoadLibrary(), and copied.
+ */
+
+static int win32_load(DSO *dso)
+{
+ HINSTANCE h = NULL, *p = NULL;
+ /* See applicable comments from dso_dl.c */
+ char *filename = DSO_convert_filename(dso, NULL);
+
+ if (filename == NULL) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
+ goto err;
+ }
+ h = LoadLibraryA(filename);
+ if (h == NULL) {
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
+ "filename(%s)", filename);
+ goto err;
+ }
+ p = OPENSSL_malloc(sizeof(*p));
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ *p = h;
+ if (!sk_void_push(dso->meth_data, p)) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR);
+ goto err;
+ }
+ /* Success */
+ dso->loaded_filename = filename;
+ return 1;
+ err:
+ /* Cleanup ! */
+ OPENSSL_free(filename);
+ OPENSSL_free(p);
+ if (h != NULL)
+ FreeLibrary(h);
+ return 0;
+}
+
+static int win32_unload(DSO *dso)
+{
+ HINSTANCE *p;
+ if (dso == NULL) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (sk_void_num(dso->meth_data) < 1)
+ return 1;
+ p = sk_void_pop(dso->meth_data);
+ if (p == NULL) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
+ return 0;
+ }
+ if (!FreeLibrary(*p)) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNLOAD_FAILED);
+ /*
+ * We should push the value back onto the stack in case of a retry.
+ */
+ sk_void_push(dso->meth_data, p);
+ return 0;
+ }
+ /* Cleanup */
+ OPENSSL_free(p);
+ return 1;
+}
+
+static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
+{
+ HINSTANCE *ptr;
+ union {
+ void *p;
+ FARPROC f;
+ } sym;
+
+ if ((dso == NULL) || (symname == NULL)) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (sk_void_num(dso->meth_data) < 1) {
+ 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) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
+ return NULL;
+ }
+ sym.f = GetProcAddress(*ptr, symname);
+ if (sym.p == NULL) {
+ ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE, "symname(%s)", symname);
+ return NULL;
+ }
+ return (DSO_FUNC_TYPE)sym.f;
+}
+
+struct file_st {
+ const char *node;
+ int nodelen;
+ const char *device;
+ int devicelen;
+ const char *predir;
+ int predirlen;
+ const char *dir;
+ int dirlen;
+ const char *file;
+ int filelen;
+};
+
+static struct file_st *win32_splitter(DSO *dso, const char *filename,
+ int assume_last_is_dir)
+{
+ struct file_st *result = NULL;
+ enum { IN_NODE, IN_DEVICE, IN_FILE } position;
+ const char *start = filename;
+ char last;
+
+ if (!filename) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
+ return NULL;
+ }
+
+ result = OPENSSL_zalloc(sizeof(*result));
+ if (result == NULL) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ position = IN_DEVICE;
+
+ if ((filename[0] == '\\' && filename[1] == '\\')
+ || (filename[0] == '/' && filename[1] == '/')) {
+ position = IN_NODE;
+ filename += 2;
+ start = filename;
+ result->node = start;
+ }
+
+ do {
+ last = filename[0];
+ switch (last) {
+ case ':':
+ if (position != IN_DEVICE) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_INCORRECT_FILE_SYNTAX);
+ OPENSSL_free(result);
+ return NULL;
+ }
+ result->device = start;
+ result->devicelen = (int)(filename - start);
+ position = IN_FILE;
+ start = ++filename;
+ result->dir = start;
+ break;
+ case '\\':
+ case '/':
+ if (position == IN_NODE) {
+ result->nodelen = (int)(filename - start);
+ position = IN_FILE;
+ start = ++filename;
+ result->dir = start;
+ } else if (position == IN_DEVICE) {
+ position = IN_FILE;
+ filename++;
+ result->dir = start;
+ result->dirlen = (int)(filename - start);
+ start = filename;
+ } else {
+ filename++;
+ result->dirlen += (int)(filename - start);
+ start = filename;
+ }
+ break;
+ case '\0':
+ if (position == IN_NODE) {
+ result->nodelen = (int)(filename - start);
+ } else {
+ if (filename - start > 0) {
+ if (assume_last_is_dir) {
+ if (position == IN_DEVICE) {
+ result->dir = start;
+ result->dirlen = 0;
+ }
+ result->dirlen += (int)(filename - start);
+ } else {
+ result->file = start;
+ result->filelen = (int)(filename - start);
+ }
+ }
+ }
+ break;
+ default:
+ filename++;
+ break;
+ }
+ }
+ while (last);
+
+ if (!result->nodelen)
+ result->node = NULL;
+ if (!result->devicelen)
+ result->device = NULL;
+ if (!result->dirlen)
+ result->dir = NULL;
+ if (!result->filelen)
+ result->file = NULL;
+
+ return result;
+}
+
+static char *win32_joiner(DSO *dso, const struct file_st *file_split)
+{
+ int len = 0, offset = 0;
+ char *result = NULL;
+ const char *start;
+
+ if (!file_split) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (file_split->node) {
+ len += 2 + file_split->nodelen; /* 2 for starting \\ */
+ if (file_split->predir || file_split->dir || file_split->file)
+ len++; /* 1 for ending \ */
+ } else if (file_split->device) {
+ len += file_split->devicelen + 1; /* 1 for ending : */
+ }
+ len += file_split->predirlen;
+ if (file_split->predir && (file_split->dir || file_split->file)) {
+ len++; /* 1 for ending \ */
+ }
+ len += file_split->dirlen;
+ if (file_split->dir && file_split->file) {
+ len++; /* 1 for ending \ */
+ }
+ len += file_split->filelen;
+
+ if (!len) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_EMPTY_FILE_STRUCTURE);
+ return NULL;
+ }
+
+ result = OPENSSL_malloc(len + 1);
+ if (result == NULL) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (file_split->node) {
+ strcpy(&result[offset], "\\\\");
+ offset += 2;
+ strncpy(&result[offset], file_split->node, file_split->nodelen);
+ offset += file_split->nodelen;
+ if (file_split->predir || file_split->dir || file_split->file) {
+ result[offset] = '\\';
+ offset++;
+ }
+ } else if (file_split->device) {
+ strncpy(&result[offset], file_split->device, file_split->devicelen);
+ offset += file_split->devicelen;
+ result[offset] = ':';
+ offset++;
+ }
+ start = file_split->predir;
+ while (file_split->predirlen > (start - file_split->predir)) {
+ const char *end = openssl_strnchr(start, '/',
+ file_split->predirlen - (start -
+ file_split->predir));
+ if (!end)
+ end = start
+ + file_split->predirlen - (start - file_split->predir);
+ strncpy(&result[offset], start, end - start);
+ offset += (int)(end - start);
+ result[offset] = '\\';
+ offset++;
+ start = end + 1;
+ }
+ start = file_split->dir;
+ while (file_split->dirlen > (start - file_split->dir)) {
+ const char *end = openssl_strnchr(start, '/',
+ file_split->dirlen - (start -
+ file_split->dir));
+ if (!end)
+ end = start + file_split->dirlen - (start - file_split->dir);
+ strncpy(&result[offset], start, end - start);
+ offset += (int)(end - start);
+ result[offset] = '\\';
+ offset++;
+ start = end + 1;
+ }
+ strncpy(&result[offset], file_split->file, file_split->filelen);
+ offset += file_split->filelen;
+ result[offset] = '\0';
+ return result;
+}
+
+static char *win32_merger(DSO *dso, const char *filespec1,
+ const char *filespec2)
+{
+ char *merged = NULL;
+ struct file_st *filespec1_split = NULL;
+ struct file_st *filespec2_split = NULL;
+
+ if (!filespec1 && !filespec2) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (!filespec2) {
+ merged = OPENSSL_strdup(filespec1);
+ if (merged == NULL) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ } else if (!filespec1) {
+ merged = OPENSSL_strdup(filespec2);
+ if (merged == NULL) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ } else {
+ filespec1_split = win32_splitter(dso, filespec1, 0);
+ if (!filespec1_split) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ filespec2_split = win32_splitter(dso, filespec2, 1);
+ if (!filespec2_split) {
+ ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(filespec1_split);
+ return NULL;
+ }
+
+ /* Fill in into filespec1_split */
+ if (!filespec1_split->node && !filespec1_split->device) {
+ filespec1_split->node = filespec2_split->node;
+ filespec1_split->nodelen = filespec2_split->nodelen;
+ filespec1_split->device = filespec2_split->device;
+ filespec1_split->devicelen = filespec2_split->devicelen;
+ }
+ if (!filespec1_split->dir) {
+ filespec1_split->dir = filespec2_split->dir;
+ filespec1_split->dirlen = filespec2_split->dirlen;
+ } else if (filespec1_split->dir[0] != '\\'
+ && filespec1_split->dir[0] != '/') {
+ filespec1_split->predir = filespec2_split->dir;
+ filespec1_split->predirlen = filespec2_split->dirlen;
+ }
+ if (!filespec1_split->file) {
+ filespec1_split->file = filespec2_split->file;
+ filespec1_split->filelen = filespec2_split->filelen;
+ }
+
+ merged = win32_joiner(dso, filespec1_split);
+ }
+ OPENSSL_free(filespec1_split);
+ OPENSSL_free(filespec2_split);
+ return merged;
+}
+
+static char *win32_name_converter(DSO *dso, const char *filename)
+{
+ char *translated;
+ int len, transform;
+
+ transform = ((strstr(filename, "/") == NULL) &&
+ (strstr(filename, "\\") == NULL) &&
+ (strstr(filename, ":") == NULL));
+ /* If transform != 0, then we convert to %s.dll, else just dupe filename */
+
+ len = strlen(filename) + 1;
+ if (transform)
+ len += strlen(".dll");
+ translated = OPENSSL_malloc(len);
+ if (translated == NULL) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED);
+ return NULL;
+ }
+ BIO_snprintf(translated, len, "%s%s", filename, transform ? ".dll" : "");
+ return translated;
+}
+
+static const char *openssl_strnchr(const char *string, int c, size_t len)
+{
+ size_t i;
+ const char *p;
+ for (i = 0, p = string; i < len && *p; i++, p++) {
+ if (*p == c)
+ return p;
+ }
+ return NULL;
+}
+
+# include <tlhelp32.h>
+# ifdef _WIN32_WCE
+# define DLLNAME "TOOLHELP.DLL"
+# else
+# ifdef MODULEENTRY32
+# undef MODULEENTRY32 /* unmask the ASCII version! */
+# endif
+# define DLLNAME "KERNEL32.DLL"
+# endif
+
+typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
+typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
+typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *);
+
+static int win32_pathbyaddr(void *addr, char *path, int sz)
+{
+ HMODULE dll;
+ HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
+ MODULEENTRY32 me32;
+ CREATETOOLHELP32SNAPSHOT create_snap;
+ CLOSETOOLHELP32SNAPSHOT close_snap;
+ MODULE32 module_first, module_next;
+
+ if (addr == NULL) {
+ union {
+ int (*f) (void *, char *, int);
+ void *p;
+ } t = {
+ win32_pathbyaddr
+ };
+ addr = t.p;
+ }
+
+ dll = LoadLibrary(TEXT(DLLNAME));
+ if (dll == NULL) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
+ return -1;
+ }
+
+ create_snap = (CREATETOOLHELP32SNAPSHOT)
+ GetProcAddress(dll, "CreateToolhelp32Snapshot");
+ if (create_snap == NULL) {
+ FreeLibrary(dll);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
+ return -1;
+ }
+ /* We take the rest for granted... */
+# ifdef _WIN32_WCE
+ close_snap = (CLOSETOOLHELP32SNAPSHOT)
+ GetProcAddress(dll, "CloseToolhelp32Snapshot");
+# else
+ close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
+# endif
+ module_first = (MODULE32) GetProcAddress(dll, "Module32First");
+ module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
+
+ /*
+ * Take a snapshot of current process which includes
+ * list of all involved modules.
+ */
+ hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
+ if (hModuleSnap == INVALID_HANDLE_VALUE) {
+ FreeLibrary(dll);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
+ return -1;
+ }
+
+ me32.dwSize = sizeof(me32);
+
+ if (!(*module_first) (hModuleSnap, &me32)) {
+ (*close_snap) (hModuleSnap);
+ FreeLibrary(dll);
+ ERR_raise(ERR_LIB_DSO, DSO_R_FAILURE);
+ return -1;
+ }
+
+ /* Enumerate the modules to find one which includes me. */
+ do {
+ if ((size_t) addr >= (size_t) me32.modBaseAddr &&
+ (size_t) addr < (size_t) (me32.modBaseAddr + me32.modBaseSize)) {
+ (*close_snap) (hModuleSnap);
+ FreeLibrary(dll);
+# ifdef _WIN32_WCE
+# if _WIN32_WCE >= 101
+ return WideCharToMultiByte(CP_ACP, 0, me32.szExePath, -1,
+ path, sz, NULL, NULL);
+# else
+ {
+ int i, len = (int)wcslen(me32.szExePath);
+ if (sz <= 0)
+ return len + 1;
+ if (len >= sz)
+ len = sz - 1;
+ for (i = 0; i < len; i++)
+ path[i] = (char)me32.szExePath[i];
+ path[len++] = '\0';
+ return len;
+ }
+# endif
+# else
+ {
+ int len = (int)strlen(me32.szExePath);
+ if (sz <= 0)
+ return len + 1;
+ if (len >= sz)
+ len = sz - 1;
+ memcpy(path, me32.szExePath, len);
+ path[len++] = '\0';
+ return len;
+ }
+# endif
+ }
+ } while ((*module_next) (hModuleSnap, &me32));
+
+ (*close_snap) (hModuleSnap);
+ FreeLibrary(dll);
+ return 0;
+}
+
+static void *win32_globallookup(const char *name)
+{
+ HMODULE dll;
+ HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
+ MODULEENTRY32 me32;
+ CREATETOOLHELP32SNAPSHOT create_snap;
+ CLOSETOOLHELP32SNAPSHOT close_snap;
+ MODULE32 module_first, module_next;
+ union {
+ void *p;
+ FARPROC f;
+ } ret = { NULL };
+
+ dll = LoadLibrary(TEXT(DLLNAME));
+ if (dll == NULL) {
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
+ return NULL;
+ }
+
+ create_snap = (CREATETOOLHELP32SNAPSHOT)
+ GetProcAddress(dll, "CreateToolhelp32Snapshot");
+ if (create_snap == NULL) {
+ FreeLibrary(dll);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
+ return NULL;
+ }
+ /* We take the rest for granted... */
+# ifdef _WIN32_WCE
+ close_snap = (CLOSETOOLHELP32SNAPSHOT)
+ GetProcAddress(dll, "CloseToolhelp32Snapshot");
+# else
+ close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
+# endif
+ module_first = (MODULE32) GetProcAddress(dll, "Module32First");
+ module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
+
+ hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
+ if (hModuleSnap == INVALID_HANDLE_VALUE) {
+ FreeLibrary(dll);
+ ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
+ return NULL;
+ }
+
+ me32.dwSize = sizeof(me32);
+
+ if (!(*module_first) (hModuleSnap, &me32)) {
+ (*close_snap) (hModuleSnap);
+ FreeLibrary(dll);
+ return NULL;
+ }
+
+ do {
+ if ((ret.f = GetProcAddress(me32.hModule, name))) {
+ (*close_snap) (hModuleSnap);
+ FreeLibrary(dll);
+ return ret.p;
+ }
+ } while ((*module_next) (hModuleSnap, &me32));
+
+ (*close_snap) (hModuleSnap);
+ FreeLibrary(dll);
+ return NULL;
+}
+#endif /* DSO_WIN32 */
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..cf3bc79085f8
--- /dev/null
+++ b/crypto/ec/asm/ecp_nistp521-ppc64.pl
@@ -0,0 +1,436 @@
+#! /usr/bin/env perl
+# 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
+# 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.=<<___;
+.machine "any"
+.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..6dd98e9f4f17 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.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_impl.c b/crypto/ec/curve448/arch_32/f_impl32.c
index 8a89d276edb6..8714a5142216 100644
--- a/crypto/ec/curve448/arch_32/f_impl.c
+++ b/crypto/ec/curve448/arch_32/f_impl32.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 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
@@ -10,7 +10,16 @@
* Originally written by Mike Hamburg
*/
-#include "field.h"
+#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)
{
@@ -93,3 +102,4 @@ 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..dfe75b8fc5ca
--- /dev/null
+++ b/crypto/ec/curve448/arch_64/f_impl64.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2017-2024 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 + 8 - j]);
+ accum1 += widemul(aa[j], bbb[i + 4 - j]);
+ accum0 += widemul(a[j + 4], bb[i + 4 - j]);
+ }
+
+ 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..c018f392894d 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;
@@ -1219,8 +1161,8 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
size_t buf_len = 0;
int new_buffer = 0;
- if (a == NULL) {
- ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
+ if (a == NULL || a->pub_key == NULL) {
+ 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..cad576fc48a1
--- /dev/null
+++ b/crypto/ec/ec_backend.c
@@ -0,0 +1,836 @@
+/*
+ * 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)
+ 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..480376686b9e 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-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,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"},
@@ -369,6 +108,7 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
"random number generation failed"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_SHARED_INFO_ERROR), "shared info error"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_SLOT_FULL), "slot full"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_TOO_MANY_RETRIES), "too many retries"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_GENERATOR), "undefined generator"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_ORDER), "undefined order"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_COFACTOR), "unknown cofactor"},
@@ -381,15 +121,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..a082876fb479 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -1,41 +1,59 @@
/*
- * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2025 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 "crypto/bn.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 +63,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 +72,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 +133,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 +156,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 +248,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 +271,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 +286,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 +296,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 +329,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 +365,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 +383,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 +393,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 +481,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 +492,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 +534,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 +557,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 +567,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 +604,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 +613,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 +623,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 +637,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 +653,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 +667,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 +718,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 +745,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 +755,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 +768,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 +802,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 +845,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 +903,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 +939,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 +954,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 +967,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 +980,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 +1001,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 +1015,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 +1045,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 +1064,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 +1085,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 +1103,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 +1169,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 +1177,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 +1185,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 +1212,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 +1222,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 +1235,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);
@@ -1155,17 +1263,19 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
if (!BN_sub(e, group->order, e))
goto err;
/*-
- * Exponent e is public.
- * No need for scatter-gather or BN_FLG_CONSTTIME.
+ * Although the exponent is public we want the result to be
+ * fixed top.
*/
- if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
+ if (!bn_mod_exp_mont_fixed_top(r, x, e, group->order, ctx, group->mont_data))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
+#ifndef FIPS_MODULE
BN_CTX_free(new_ctx);
+#endif
return ret;
}
@@ -1182,8 +1292,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 +1311,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..2b77e9738883 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)
@@ -71,27 +74,32 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form, unsigned char *buf,
size_t len, BN_CTX *ctx)
{
+ if (point == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
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 +111,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 +145,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..775b7ec911be 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,18 +20,67 @@
#include "crypto/bn.h"
#include "ec_local.h"
+#define MIN_ECDSA_SIGN_ORDERBITS 64
+/*
+ * It is highly unlikely that a retry will happen,
+ * Multiple retries would indicate that something is wrong
+ * with the group parameters (which would normally only happen
+ * with a bad custom group).
+ */
+#define MAX_ECDSA_SIGN_RETRIES 8
+
+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)
{
ECDSA_SIG *s;
+ if (sig == NULL && (kinv == NULL || r == NULL)) {
+ *siglen = ECDSA_size(eckey);
+ return 1;
+ }
+
s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
if (s == NULL) {
*siglen = 0;
return 0;
}
- *siglen = i2d_ECDSA_SIG(s, &sig);
+ *siglen = i2d_ECDSA_SIG(s, sig != NULL ? &sig : NULL);
ECDSA_SIG_free(s);
return 1;
}
@@ -44,42 +99,48 @@ 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;
+ }
+
+ if ((order = EC_GROUP_get0_order(group)) == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
- order = EC_GROUP_get0_order(group);
/* Preallocate space */
order_bits = BN_num_bits(order);
- if (!BN_set_bit(k, order_bits)
+ /* Check the number of bits here so that an infinite loop is not possible */
+ if (order_bits < MIN_ECDSA_SIGN_ORDERBITS
+ || !BN_set_bit(k, order_bits)
|| !BN_set_bit(r, order_bits)
|| !BN_set_bit(X, order_bits))
goto err;
@@ -88,41 +149,39 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
/* get random k */
do {
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);
+ if (!ossl_bn_gen_dsa_nonce_fixed_top(k, order, priv_key,
+ dgst, dlen, ctx)) {
+ 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 (!ossl_bn_priv_rand_range_fixed_top(k, order, 0, ctx)) {
+ ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
}
- } while (BN_is_zero(k));
+ } while (ossl_bn_is_word_fixed_top(k, 0));
/* 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,17 +204,18 @@ 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;
+ int retries = 0;
BIGNUM *kinv = NULL, *s, *m = NULL;
const BIGNUM *order, *ckinv;
BN_CTX *ctx = NULL;
@@ -167,39 +227,43 @@ 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;
+ }
+
+ if ((order = EC_GROUP_get0_order(group)) == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
- order = EC_GROUP_get0_order(group);
i = BN_num_bits(order);
/*
* Need to truncate digest if it is too long: first truncate whole bytes.
@@ -207,25 +271,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 +303,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 +316,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 +326,12 @@ 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;
+ }
+ /* Avoid infinite loops cause by invalid group parameters */
+ if (retries++ > MAX_ECDSA_SIGN_RETRIES) {
+ ERR_raise(ERR_LIB_EC, EC_R_TOO_MANY_RETRIES);
goto err;
}
} else {
@@ -314,8 +383,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 +397,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 +417,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 +447,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..e42767d6bf0f
--- /dev/null
+++ b/crypto/ec/ecx_backend.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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 = 0;
+ 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
+ && key->haspubkey == 1) {
+ memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey));
+ ret->haspubkey = 1;
+ }
+
+ 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..c97dc472ac57 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-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
*/
+/*
+ * 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_KEYGEN, 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..2e4b7ed60b9c
--- /dev/null
+++ b/crypto/encode_decode/decoder_lib.c
@@ -0,0 +1,1000 @@
+/*
+ * 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
+ */
+
+#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);
+
+ ok = (rv > 0);
+ if (ok) {
+ data->flag_construct_called = 1;
+ 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..ad5e2805319b
--- /dev/null
+++ b/crypto/encode_decode/decoder_pkey.c
@@ -0,0 +1,466 @@
+/*
+ * 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
+ */
+
+#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;
+ if (data->selection == 0)
+ /* import/export functions do not tolerate 0 selection */
+ import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
+ else
+ 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..a88332b79d52
--- /dev/null
+++ b/crypto/encode_decode/encoder_lib.c
@@ -0,0 +1,679 @@
+/*
+ * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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;
+ }
+
+ if (ctx->cleanup == NULL || ctx->construct == NULL) {
+ ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INIT_FAIL);
+ 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..b372170db256
--- /dev/null
+++ b/crypto/encode_decode/encoder_pkey.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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) {
+ int selection = data->selection;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ data->encoder_inst = encoder_inst;
+
+ if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, 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;
+ int match = (data->obj == data->constructed_obj);
+
+ 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;
+ if (match)
+ data->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.md
index 0f8a8fbde410..b45115ca2481 100644
--- a/crypto/engine/README
+++ b/crypto/engine/README.md
@@ -1,12 +1,12 @@
-Notes: 2001-09-24
------------------
+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 or the commit mails :-).
+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;
@@ -21,16 +21,16 @@ 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() ...]
+ (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 ... ]
+ (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
@@ -177,7 +177,7 @@ 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_***"
+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
@@ -208,4 +208,3 @@ 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..cfdb5a50f481 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.
+ * Copyright 2001-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,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,34 +126,41 @@ 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;
return item;
}
-void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb)
+int engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb)
{
ENGINE_CLEANUP_ITEM *item;
if (!int_cleanup_check(1))
- return;
+ return 0;
item = int_cleanup_item(cb);
- if (item)
- sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0);
+ if (item != NULL) {
+ if (sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0))
+ return 1;
+ OPENSSL_free(item);
+ }
+ return 0;
}
-void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
+int engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
{
ENGINE_CLEANUP_ITEM *item;
+
if (!int_cleanup_check(1))
- return;
+ return 0;
item = int_cleanup_item(cb);
if (item != NULL) {
- if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) <= 0)
- OPENSSL_free(item);
+ if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) > 0)
+ return 1;
+ OPENSSL_free(item);
}
+ return 0;
}
/* The API function that performs all cleanup */
@@ -196,7 +201,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 +211,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..f2eed3b07174 100644
--- a/crypto/engine/eng_list.c
+++ b/crypto/engine/eng_list.c
@@ -1,13 +1,16 @@
/*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2023 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,25 +69,28 @@ 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;
- e->prev = NULL;
/*
* The first time the list allocates, we should register the cleanup.
*/
- engine_cleanup_add_last(engine_list_cleanup);
+ if (!engine_cleanup_add_last(engine_list_cleanup)) {
+ ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ engine_list_head = e;
+ e->prev = NULL;
} 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 +100,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 +112,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 +120,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 +222,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 +242,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 +262,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 +283,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 +305,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 +327,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 +344,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 +375,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 +406,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 +430,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 +439,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..75bc9e6f1675 100644
--- a/crypto/engine/eng_local.h
+++ b/crypto/engine/eng_local.h
@@ -1,8 +1,8 @@
/*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2023 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
@@ -52,21 +46,13 @@ typedef struct st_engine_cleanup_item {
ENGINE_CLEANUP_CB *cb;
} ENGINE_CLEANUP_ITEM;
DEFINE_STACK_OF(ENGINE_CLEANUP_ITEM)
-void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb);
-void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb);
+int engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb);
+int engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb);
/* We need stacks of ENGINEs for use in eng_table.c */
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..d18d837e625c 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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..6280965cc026 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,14 +86,19 @@ 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))
goto end;
- if (added)
- /* The cleanup callback needs to be added */
- engine_cleanup_add_first(cleanup);
+ /* The cleanup callback needs to be added */
+ if (added && !engine_cleanup_add_first(cleanup)) {
+ lh_ENGINE_PILE_free(&(*table)->piles);
+ *table = NULL;
+ goto end;
+ }
while (num_nids--) {
tmplate.nid = *nids;
fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
@@ -126,8 +132,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 +166,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 +176,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 +186,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 +197,32 @@ 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;
- if (!(*table)) {
-#ifdef ENGINE_TABLE_DEBUG
- fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing "
- "registered!\n", f, l, nid);
+#ifndef OPENSSL_NO_AUTOLOAD_CONFIG
+ /* Load the config before trying to check if engines are available */
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
#endif
+
+ if (!(*table)) {
+ OSSL_TRACE3(ENGINE_TABLE,
+ "%s:%d, nid=%d, nothing registered!\n",
+ f, l, nid);
return NULL;
}
+
+ if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+ return NULL;
+
ERR_set_mark();
- CRYPTO_THREAD_write_lock(global_engine_lock);
/*
* 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 +231,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 +244,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 +262,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 +279,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.ec b/crypto/err/openssl.ec
new file mode 100644
index 000000000000..f3802a05b5c3
--- /dev/null
+++ b/crypto/err/openssl.ec
@@ -0,0 +1,81 @@
+# configuration file for util/mkerr.pl
+
+# The INPUT HEADER is scanned for declarations
+# LIBNAME PUBLIC HEADER ERROR-TABLE FILE INTERNAL HEADER (if relevant)
+L ERR NONE NONE
+L FUNC NONE NONE
+L BN include/openssl/bnerr.h crypto/bn/bn_err.c include/crypto/bnerr.h
+L RSA include/openssl/rsaerr.h crypto/rsa/rsa_err.c include/crypto/rsaerr.h
+L DH include/openssl/dherr.h crypto/dh/dh_err.c include/crypto/dherr.h
+L EVP include/openssl/evperr.h crypto/evp/evp_err.c include/crypto/evperr.h
+L BUF include/openssl/buffererr.h crypto/buffer/buf_err.c include/crypto/buffererr.h
+L OBJ include/openssl/objectserr.h crypto/objects/obj_err.c include/crypto/objectserr.h
+L PEM include/openssl/pemerr.h crypto/pem/pem_err.c include/crypto/pemerr.h
+L DSA include/openssl/dsaerr.h crypto/dsa/dsa_err.c include/crypto/dsaerr.h
+L X509 include/openssl/x509err.h crypto/x509/x509_err.c include/crypto/x509err.h
+L ASN1 include/openssl/asn1err.h crypto/asn1/asn1_err.c include/crypto/asn1err.h
+L CONF include/openssl/conferr.h crypto/conf/conf_err.c include/crypto/conferr.h
+L CRYPTO include/openssl/cryptoerr.h crypto/cpt_err.c include/crypto/cryptoerr.h
+L EC include/openssl/ecerr.h crypto/ec/ec_err.c include/crypto/ecerr.h
+L SSL include/openssl/sslerr.h ssl/ssl_err.c ssl/sslerr.h
+L BIO include/openssl/bioerr.h crypto/bio/bio_err.c include/crypto/bioerr.h
+L PKCS7 include/openssl/pkcs7err.h crypto/pkcs7/pkcs7err.c include/crypto/pkcs7err.h
+L X509V3 include/openssl/x509v3err.h crypto/x509/v3err.c include/crypto/x509v3err.h
+L PKCS12 include/openssl/pkcs12err.h crypto/pkcs12/pk12err.c include/crypto/pkcs12err.h
+L RAND include/openssl/randerr.h crypto/rand/rand_err.c include/crypto/randerr.h
+L DSO NONE crypto/dso/dso_err.c include/internal/dsoerr.h
+L ENGINE include/openssl/engineerr.h crypto/engine/eng_err.c include/crypto/engineerr.h
+L OCSP include/openssl/ocsperr.h crypto/ocsp/ocsp_err.c include/crypto/ocsperr.h
+L UI include/openssl/uierr.h crypto/ui/ui_err.c include/crypto/uierr.h
+L COMP include/openssl/comperr.h crypto/comp/comp_err.c include/crypto/comperr.h
+L TS include/openssl/tserr.h crypto/ts/ts_err.c include/crypto/tserr.h
+L CMS include/openssl/cmserr.h crypto/cms/cms_err.c include/crypto/cmserr.h
+L CRMF include/openssl/crmferr.h crypto/crmf/crmf_err.c include/crypto/crmferr.h
+L CMP include/openssl/cmperr.h crypto/cmp/cmp_err.c include/crypto/cmperr.h
+L CT include/openssl/cterr.h crypto/ct/ct_err.c include/crypto/cterr.h
+L ASYNC include/openssl/asyncerr.h crypto/async/async_err.c include/crypto/asyncerr.h
+# KDF is only here for conservation purposes
+L KDF NONE NONE NONE
+L SM2 NONE crypto/sm2/sm2_err.c include/crypto/sm2err.h
+L OSSL_STORE include/openssl/storeerr.h crypto/store/store_err.c include/crypto/storeerr.h
+L ESS include/openssl/esserr.h crypto/ess/ess_err.c include/crypto/esserr.h
+L PROP NONE crypto/property/property_err.c include/internal/propertyerr.h
+L PROV include/openssl/proverr.h providers/common/provider_err.c providers/common/include/prov/proverr.h
+L OSSL_ENCODER include/openssl/encodererr.h crypto/encode_decode/encoder_err.c include/crypto/encodererr.h
+L OSSL_DECODER include/openssl/decodererr.h crypto/encode_decode/decoder_err.c include/crypto/decodererr.h
+L HTTP include/openssl/httperr.h crypto/http/http_err.c include/crypto/httperr.h
+
+# SSL/TLS alerts
+R SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
+R SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
+R SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021
+R SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022
+R SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030
+R SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040
+R SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041
+R SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042
+R SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043
+R SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044
+R SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045
+R SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046
+R SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047
+R SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048
+R SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049
+R SSL_R_TLSV1_ALERT_DECODE_ERROR 1050
+R SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051
+R SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060
+R SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070
+R SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
+R SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
+R SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086
+R SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
+R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
+R SSL_R_TLSV13_ALERT_MISSING_EXTENSION 1109
+R SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
+R SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111
+R SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
+R SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113
+R SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114
+R SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY 1115
+R SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED 1116
+R SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL 1120
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index ba3a46d5b988..756fafdfa24a 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-2025 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with 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,111 @@ 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_PRIVATE_KEY_FOR_POPO:190:missing private key for popo
+CMP_R_MISSING_PROTECTION:143:missing protection
+CMP_R_MISSING_PUBLIC_KEY:183:missing public key
+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 +300,22 @@ 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_ERROR_UNSUPPORTED_STATIC_KEY_AGREEMENT:196:\
+ error unsupported static key agreement
+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 +347,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,11 +370,14 @@ 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_SIGNATURE_ALGORITHM:195:unsupported signature algorithm
CMS_R_UNSUPPORTED_TYPE:156:unsupported type
CMS_R_UNWRAP_ERROR:157:unwrap error
CMS_R_UNWRAP_FAILURE:180:unwrap failure
@@ -2041,7 +387,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 +402,11 @@ 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_RECURSIVE_SECTION_REFERENCE:126:recursive section reference
+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 +415,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 +476,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,17 +492,21 @@ 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
DH_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error
DH_R_PEER_KEY_ERROR:111:peer key error
+DH_R_Q_TOO_LARGE:130:q too large
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,8 +518,10 @@ 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
+DSA_R_TOO_MANY_RETRIES:116:too many retries
DSO_R_CTRL_FAILED:100:control command failed
DSO_R_DSO_ALREADY_LOADED:110:dso already loaded
DSO_R_EMPTY_FILE_STRUCTURE:113:empty file structure
@@ -2144,17 +545,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 +569,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 +598,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
@@ -2195,6 +605,7 @@ EC_R_POINT_IS_NOT_ON_CURVE:107:point is not on curve
EC_R_RANDOM_NUMBER_GENERATION_FAILED:158:random number generation failed
EC_R_SHARED_INFO_ERROR:150:shared info error
EC_R_SLOT_FULL:108:slot full
+EC_R_TOO_MANY_RETRIES:176:too many retries
EC_R_UNDEFINED_GENERATOR:113:undefined generator
EC_R_UNDEFINED_ORDER:128:undefined order
EC_R_UNKNOWN_COFACTOR:164:unknown cofactor
@@ -2238,58 +649,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 +742,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 +761,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 +823,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 +831,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 +848,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 +874,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 +905,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 +914,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 +959,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 +1116,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 +1135,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 +1168,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 +1204,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 +1240,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 +1248,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 +1290,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 +1300,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 +1311,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 +1378,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 +1427,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 +1498,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 +1510,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 +1607,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 +1622,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 +1644,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 +1676,17 @@ 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_DUPLICATE_ATTRIBUTE:140:duplicate attribute
+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 +1710,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..cd42f951f7b8
--- /dev/null
+++ b/crypto/ess/ess_lib.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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_ESS, 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..d0cb91114278 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
@@ -159,6 +159,7 @@ static int enc_read(BIO *b, char *out, int outl)
/* Should be continue next time we are called? */
if (!BIO_should_retry(next)) {
ctx->cont = i;
+ ctx->finished = 1;
i = EVP_CipherFinal_ex(ctx->cipher,
ctx->buf, &(ctx->buf_len));
ctx->ok = i;
@@ -311,7 +312,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 +396,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..cbf02dc5f831
--- /dev/null
+++ b/crypto/evp/ctrl_params_translate.c
@@ -0,0 +1,2888 @@
+/*
+ * Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with 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,
+ (size_t *)&ctx->p1);
+ 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, *(void **)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;
+ }
+ } else if (state == PRE_PARAMS_TO_CTRL && ctx->action_type == GET) {
+ if (translation->param_data_type == OSSL_PARAM_OCTET_PTR)
+ ctx->p2 = &ctx->bufp;
+ }
+ }
+ /* 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)
+{
+ char *p2 = NULL;
+ 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;
+ } else if (state == PRE_PARAMS_TO_CTRL) {
+ /*
+ * We're translating from params to ctrl and setting the curve name.
+ * The ctrl function needs it to be a NID, but meanwhile, we need
+ * space to get the curve name from the param. |ctx->name_buf| is
+ * sufficient for that.
+ * The double indirection is necessary for default_fixup_args()'s
+ * call of OSSL_PARAM_get_utf8_string() to be done correctly.
+ */
+ p2 = ctx->name_buf;
+ ctx->p2 = &p2;
+ ctx->sz = sizeof(ctx->name_buf);
+ }
+
+ if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return ret;
+
+ if (state == PRE_PARAMS_TO_CTRL) {
+ ctx->p1 = OBJ_sn2nid(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;
+ } else if (state == POST_PARAMS_TO_CTRL && ctx->action_type == NONE) {
+ ctx->action_type = GET;
+ }
+
+ 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;
+ } else if (state == POST_PARAMS_TO_CTRL && ctx->action_type == GET) {
+ ctx->p1 = ret;
+ }
+
+ 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
+ && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
+ 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
+ && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
+ 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
+ && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
+ 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 \
+ && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS) \
+ 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 \
+ && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS) \
+ 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 \
+ && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS) \
+ 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 },
+
+ /*-
+ * SM2
+ * ==
+ */
+ { SET, EVP_PKEY_SM2, 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_SM2, 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_SM2, 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_SM2, 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_SM2, 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_SM2, 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_SM2, 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_SM2, 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_SM2, 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_SM2, 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_PTR, 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, EVP_PKEY_RSA_PSS, 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, EVP_PKEY_RSA_PSS, 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_X25519, EVP_PKEY_X25519, EVP_PKEY_OP_PARAMGEN, -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 },
+ { SET, EVP_PKEY_X448, EVP_PKEY_X448, EVP_PKEY_OP_PARAMGEN, -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;
+
+ ctx.action_type = 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.ctrl_cmd = translation->ctrl_num;
+ }
+ 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.
+ *
+ * NOTE: even though EVP_PKEY_CTX_ctrl return value is documented
+ * as return positive on Success and 0 or negative on falure. There
+ * maybe parameters (e.g. ecdh_cofactor), which actually return 0
+ * as success value. That is why we do POST_PARAMS_TO_CTRL for 0
+ * value as well
+ */
+ 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)
+{
+ if (ctx->keymgmt != NULL)
+ return 0;
+ 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)
+{
+ if (ctx->keymgmt != NULL)
+ return 0;
+ 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..aca05186ec10 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.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,32 +331,85 @@ 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;
- return ctx->update(ctx, data, count);
+ 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 != NULL ? ctx->update(ctx, data, count) : 0;
}
/* The caller can assume that this removes any secret data from the context */
@@ -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 = (unsigned 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_ctx_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..949de68077ec 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.
+ * Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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)
@@ -1031,13 +831,11 @@ typedef struct {
/* KMO-AES parameter block - end */
} kmo;
unsigned int fc;
-
- int res;
} S390X_AES_OFB_CTX;
typedef struct {
union {
- double align;
+ OSSL_UNION_ALIGN;
/*-
* KMF-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-08)
@@ -1049,13 +847,11 @@ typedef struct {
/* KMF-AES parameter block - end */
} kmf;
unsigned int fc;
-
- int res;
} S390X_AES_CFB_CTX;
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 +895,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 +950,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 +962,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);
+ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
- cctx->fc = S390X_AES_FC(keylen) | (enc ? 0 : S390X_DECRYPT);
-
- 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 +986,18 @@ 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,9 +1005,9 @@ 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 n = ctx->num;
int rem;
memcpy(cctx->kmo.param.cv, iv, ivlen);
@@ -1275,37 +1040,26 @@ static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
memcpy(iv, cctx->kmo.param.cv, ivlen);
- cctx->res = n;
+ ctx->num = n;
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,11 +1067,11 @@ 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 n = ctx->num;
int rem;
unsigned char tmp;
@@ -1355,34 +1109,26 @@ static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
memcpy(iv, cctx->kmf.param.cv, ivlen);
- cctx->res = n;
+ ctx->num = n;
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);
-
- cctx->fc = S390X_AES_FC(keylen) | (enc ? 0 : S390X_DECRYPT)
- | (1 << 24); /* 1 byte cipher feedback flag */
+ 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 |= 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 +1136,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 +1145,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 +1159,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 +1308,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 +1320,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 +1348,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 +1372,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 +1393,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 +1402,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 +1426,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 +1437,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 +1452,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 +1469,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 +1478,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 +1492,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 +1513,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 +1562,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 +1649,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 +1669,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 +1693,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 +1805,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 +1860,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 +1872,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 +1890,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 +1918,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 +1965,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 +1989,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 +2014,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 +2038,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 +2053,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 +2087,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 +2107,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 +2125,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 +2139,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 +2147,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 +2163,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 +2177,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 +2269,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 +2281,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 +2295,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 +2310,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 +2328,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 +2347,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 +2356,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 +2376,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 +2393,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 +2405,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 +2418,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 +2433,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 +2451,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 +2463,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 +2476,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 +2490,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 +2522,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 +2554,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 +2566,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 +2585,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 +2655,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 +2687,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 +2727,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 +2790,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 +2911,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 +2947,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 +3125,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 +3147,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 +3162,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 +3184,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 +3207,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 +3233,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 +3284,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 +3304,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 +3320,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 +3335,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 +3345,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 +3382,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 +3395,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 +3405,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 +3413,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 +3428,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 +3489,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 +3503,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 +3544,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 +3561,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 +3591,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 +3599,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 +3625,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 +3634,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 +3650,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 +3664,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 +3678,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 +3692,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 +3706,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 +3720,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 +3743,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 +3763,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 +3771,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 +3796,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 +3811,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 +3827,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 +3842,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 +3910,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 +3939,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 +3964,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 +3990,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 +4009,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..c1cf221a0db5
--- /dev/null
+++ b/crypto/evp/ec_ctrl.c
@@ -0,0 +1,302 @@
+/*
+ * 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
+ */
+
+#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)
+{
+ int keytype = nid == EVP_PKEY_SM2 ? EVP_PKEY_SM2 : EVP_PKEY_EC;
+
+ return EVP_PKEY_CTX_ctrl(ctx, keytype, 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..4e6f83e3d0a9 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.
+ * 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 <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,209 @@ 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 (!ossl_assert(cipher->prov != NULL)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+
+ if (cipher != ctx->fetched_cipher) {
+ 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
- * EVP_CIPHER could be used).
+ * If this ctx was already set up for no padding then we need to tell
+ * the new cipher about it.
*/
- if (ctx->cipher
-#ifndef OPENSSL_NO_ENGINE
- || ctx->engine
+ if (!EVP_CIPHER_CTX_set_padding(ctx, 0))
+ return 0;
+ }
+
+#ifndef FIPS_MODULE
+ /*
+ * Fix for CVE-2023-5363
+ * Passing in a size as part of the init call takes effect late
+ * so, force such to occur before the initialisation.
+ *
+ * The FIPS provider's internal library context is used in a manner
+ * such that this is not an issue.
+ */
+ if (params != NULL) {
+ OSSL_PARAM param_lens[3] = { OSSL_PARAM_END, OSSL_PARAM_END,
+ OSSL_PARAM_END };
+ OSSL_PARAM *q = param_lens;
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL)
+ memcpy(q++, p, sizeof(*q));
+
+ /*
+ * Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synomym for
+ * OSSL_CIPHER_PARAM_IVLEN so both are covered here.
+ */
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL)
+ memcpy(q++, p, sizeof(*q));
+
+ if (q != param_lens) {
+ if (!EVP_CIPHER_CTX_set_params(ctx, param_lens)) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
+ return 0;
+ }
+ }
+ }
#endif
- || ctx->cipher_data) {
+
+ 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) {
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 +334,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 +344,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 +354,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 +393,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 +421,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 +431,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 +491,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 +511,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 +541,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 +559,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 +581,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 +618,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 +649,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,12 +712,51 @@ 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);
@@ -443,8 +776,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 +797,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 +865,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 +878,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 +892,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 +932,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 +993,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 +1001,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 +1012,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 +1032,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;
+ }
+
+ 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;
}
-#ifndef OPENSSL_NO_ENGINE
+
+ 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 +1457,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 +1466,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..6eeafd948ea1
--- /dev/null
+++ b/crypto/evp/evp_fetch.c
@@ -0,0 +1,703 @@
+/*
+ * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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.
+ * Note that there is a corner case here, in which, if a user
+ * passes a name of the form name1:name2:..., then the construction
+ * will create a method against all names, but the lookup will fail
+ * as ossl_namemap_name2num treats the name string as a single name
+ * rather than introducing new features where in the EVP_<obj>_fetch
+ * parses the string and querys for each, return an error.
+ */
+ if (name_id == 0)
+ name_id = ossl_namemap_name2num(namemap, name);
+ if (name_id == 0) {
+ ERR_raise_data(ERR_LIB_EVP, ERR_R_FETCH_FAILED,
+ "Algorithm %s cannot be found", name);
+ free_method(method);
+ method = NULL;
+ } else {
+ meth_id = evp_method_id(name_id, operation_id);
+ if (meth_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..1eb03a119a64 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,43 @@ 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_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen,
+ PKCS5_v2_PBKDF2_keyivgen_ex},
{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 +80,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)
+ md = 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 +201,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 +217,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 +227,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 +239,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 +259,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..99c2da0b161d
--- /dev/null
+++ b/crypto/evp/evp_rand.c
@@ -0,0 +1,680 @@
+/*
+ * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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 ctx->meth->nonce(ctx->algctx, out, str, outlen, outlen) > 0;
+ 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..859c77ca420e
--- /dev/null
+++ b/crypto/evp/exchange.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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;
+ ret = ctx->op.kex.exchange->set_peer(ctx->op.kex.algctx, provkey);
+ if (ret <= 0)
+ return ret;
+ EVP_PKEY_free(ctx->peerkey);
+ ctx->peerkey = peer;
+ EVP_PKEY_up_ref(peer);
+ return 1;
+
+ 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..9512cc9cf0f7
--- /dev/null
+++ b/crypto/evp/keymgmt_lib.c
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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.
+ * A keymgmt is a match if the |keymgmt| pointers are identical or if the
+ * provider and the name ID match
+ */
+ for (i = 0; i < end; i++) {
+ p = sk_OP_CACHE_ELEM_value(pk->operation_cache, i);
+ if ((p->selection & selection) == selection
+ && (keymgmt == p->keymgmt
+ || (keymgmt->name_id == p->keymgmt->name_id
+ && keymgmt->prov == p->keymgmt->prov)))
+ 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..b1e8870e36ac
--- /dev/null
+++ b/crypto/evp/keymgmt_meth.c
@@ -0,0 +1,496 @@
+/*
+ * 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 <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_cleanup != 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..02ce0f042c5a
--- /dev/null
+++ b/crypto/evp/legacy_sha.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with 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;
+
+ if (evp_ctx == NULL)
+ return 0;
+ 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_MD_FLAG_DIGALGID_ABSENT, \
+ 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_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..efd2c05c85cf 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,34 @@ 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) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ return -1;
+ }
+
+ if (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 (pctx->pmeth != NULL && pctx->pmeth->digestverify != NULL)
+ return 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..7ff850f99753 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the 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,128 @@ 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;
+ int do_retry = 1;
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);
+ retry:
+ id = ossl_namemap_name2num(namemap, name);
+ if (id == 0) {
+ EVP_CIPHER *fetched_cipher;
+
+ /* Try to fetch it because the name might not be known yet. */
+ if (!do_retry)
+ return NULL;
+ do_retry = 0;
+ ERR_set_mark();
+ fetched_cipher = EVP_CIPHER_fetch(libctx, name, NULL);
+ EVP_CIPHER_free(fetched_cipher);
+ ERR_pop_to_mark();
+ goto retry;
+ }
+
+ 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;
+ int do_retry = 1;
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);
+ retry:
+ id = ossl_namemap_name2num(namemap, name);
+ if (id == 0) {
+ EVP_MD *fetched_md;
+
+ /* Try to fetch it because the name might not be known yet. */
+ if (!do_retry)
+ return NULL;
+ do_retry = 0;
+ ERR_set_mark();
+ fetched_md = EVP_MD_fetch(libctx, name, NULL);
+ EVP_MD_free(fetched_md);
+ ERR_pop_to_mark();
+ goto retry;
+ }
+
+ 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..356173902334 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,23 @@ 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);
+ (void)ERR_set_mark();
+ 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);
+ (void)ERR_clear_last_mark();
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRF);
goto err;
}
+ (void)ERR_pop_to_mark();
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 +251,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..6ff7eb7e02cf 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,153 @@ 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:
+ case EVP_PKEY_RSA_PSS:
+ pkey->foreign = pkey->pkey.rsa != NULL
+ && ossl_rsa_is_foreign(pkey->pkey.rsa);
+ break;
+# ifndef OPENSSL_NO_EC
+ case EVP_PKEY_SM2:
+ break;
+ 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 +864,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,118 +976,1509 @@ 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:
+ case EVP_PKEY_RSA_PSS:
+ 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_PRIVATE_KEY, 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);
}
int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
{
+ if (pkey == NULL)
+ return 0;
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)
+{
+ 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 (ptlen > INT_MAX)
+ if (pkey == NULL)
+ return 0;
+ if (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)
+ return 0;
+ if (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. It is possible (e.g. in a no-cached-fetch
+ * build), for op->keymgmt to be a different pointer to tmp_keymgmt
+ * even though the name/provider must be the same. In other words
+ * the keymgmt instance may be different but still equivalent, i.e.
+ * same algorithm/provider instance - but we make the simplifying
+ * assumption that the keydata can be used with either keymgmt
+ * instance. Not doing so introduces significant complexity and
+ * probably requires refactoring - since we would have to ripple
+ * the change in keymgmt instance up the call chain.
+ */
+ 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:
+ if (buf != NULL) {
+ if (OSSL_PARAM_modified(params))
+ OPENSSL_clear_free(buf, buf_sz);
+ else
+ OPENSSL_free(buf);
+ } else if (OSSL_PARAM_modified(params)) {
+ OPENSSL_cleanse(buffer, params[0].data_size);
+ }
+ 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..d9a22799d051 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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)();
+}
+
+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;
- return *ret;
+ }
+
+ pmeth->pkey_id = id;
+ pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
+ return pmeth;
}
-static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
+static void help_get_legacy_alg_type_from_keymgmt(const char *keytype,
+ void *arg)
{
- EVP_PKEY_CTX *ret;
- const EVP_PKEY_METHOD *pmeth;
+ int *type = arg;
+ if (*type == NID_undef)
+ *type = evp_pkey_name2type(keytype);
+}
+
+static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt)
+{
+ 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
+ }
+ }
+ /* 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 OPENSSL_NO_ENGINE
+
+#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,99 @@ 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
+# endif /* OPENSSL_NO_ENGINE */
+ if (pkey != NULL && pkey->foreign)
pmeth = EVP_PKEY_meth_find(id);
+ else
+ 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 +349,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 +360,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 +444,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->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 = *src;
- 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 +462,174 @@ 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 (pctx->keymgmt != NULL) {
+ if (!EVP_KEYMGMT_up_ref(pctx->keymgmt))
+ goto err;
+ rctx->keymgmt = pctx->keymgmt;
+ }
- rctx->peerkey = 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;
+
+ if (pctx->op.kex.exchange->dupctx != NULL)
+ 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;
+
+ if (pctx->op.sig.signature->dupctx != NULL)
+ 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;
+
+ if (pctx->op.ciph.cipher->dupctx != NULL)
+ 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;
+
+ if (pctx->op.encap.kem->dupctx != NULL)
+ 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->data = NULL;
- rctx->app_data = NULL;
- rctx->operation = pctx->operation;
+ rctx->pmeth = pctx->pmeth;
+# ifndef OPENSSL_NO_ENGINE
+ rctx->engine = pctx->engine;
+# endif
- if (pctx->pmeth->copy(rctx, pctx) > 0)
- return rctx;
+ if (pctx->peerkey != NULL)
+ EVP_PKEY_up_ref(pctx->peerkey);
+ rctx->peerkey = pctx->peerkey;
+ if (pctx->pmeth == NULL) {
+ if (rctx->operation == EVP_PKEY_OP_UNDEFINED) {
+ EVP_KEYMGMT *tmp_keymgmt = pctx->keymgmt;
+ void *provkey;
+
+ if (pctx->pkey == NULL)
+ return rctx;
+
+ 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 +637,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 +676,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 +684,991 @@ 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;
+ case EVP_PKEY_STATE_UNKNOWN:
+ break;
+#ifndef FIPS_MODULE
+ 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;
+ case EVP_PKEY_STATE_UNKNOWN:
+ break;
+#ifndef FIPS_MODULE
+ 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);
+}
+
+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 || !ctx->pmeth || !ctx->pmeth->ctrl) {
- EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
+ 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;
+ }
+
+ *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);
+}
+
+static int evp_pkey_ctx_add1_octet_string(EVP_PKEY_CTX *ctx, int fallback,
+ const char *param, int op, int ctrl,
+ const unsigned char *data,
+ int datalen)
+{
+ OSSL_PARAM os_params[2];
+ const OSSL_PARAM *gettables;
+ unsigned char *info = NULL;
+ size_t info_len = 0;
+ size_t info_alloc = 0;
+ int ret = 0;
+
+ 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;
}
- doit:
- ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
+ /* 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;
+ } else if (datalen == 0) {
+ return 1;
+ }
+
+ /* Check for older provider that doesn't support getting this parameter */
+ gettables = EVP_PKEY_CTX_gettable_params(ctx);
+ if (gettables == NULL || OSSL_PARAM_locate_const(gettables, param) == NULL)
+ return evp_pkey_ctx_set1_octet_string(ctx, fallback, param, op, ctrl,
+ data, datalen);
+
+ /* Get the original value length */
+ os_params[0] = OSSL_PARAM_construct_octet_string(param, NULL, 0);
+ os_params[1] = OSSL_PARAM_construct_end();
+
+ if (!EVP_PKEY_CTX_get_params(ctx, os_params))
+ return 0;
+
+ /* This should not happen but check to be sure. */
+ if (os_params[0].return_size == OSSL_PARAM_UNMODIFIED)
+ return 0;
+
+ info_alloc = os_params[0].return_size + datalen;
+ if (info_alloc == 0)
+ return 0;
+ info = OPENSSL_zalloc(info_alloc);
+ if (info == NULL)
+ return 0;
+ info_len = os_params[0].return_size;
+
+ os_params[0] = OSSL_PARAM_construct_octet_string(param, info, info_alloc);
+
+ /* if we have data, then go get it */
+ if (info_len > 0) {
+ if (!EVP_PKEY_CTX_get_params(ctx, os_params))
+ goto error;
+ }
+
+ /* Copy the input data */
+ memcpy(&info[info_len], data, datalen);
+ ret = EVP_PKEY_CTX_set_params(ctx, os_params);
+
+ error:
+ OPENSSL_clear_free(info, info_alloc);
+ return ret;
+}
+
+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_add1_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 +1704,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 +1726,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 +1759,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 +1944,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 +2103,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 +2111,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 +2141,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..8adf254d5eec
--- /dev/null
+++ b/crypto/evp/signature.c
@@ -0,0 +1,763 @@
+/*
+ * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+
+ 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, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+
+ 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;
+
+ if (ctx->op.sig.signature->sign == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ 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, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+
+ 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;
+
+ if (ctx->op.sig.signature->verify == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ 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, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+
+ 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;
+
+ if (ctx->op.sig.signature->verify_recover == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ 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..13b928899456 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-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 <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,16 @@ 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);
+ sk_EX_CALLBACK_free(ip->meth);
+ ip->meth = NULL;
+ 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 +180,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 +191,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 +210,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 +239,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 +257,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 +275,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 +303,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 +336,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 +367,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 +386,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 +411,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 +470,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 +499,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..fe0a82eac8a6
--- /dev/null
+++ b/crypto/ffc/ffc_backend.c
@@ -0,0 +1,130 @@
+/*
+ * 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
+ */
+
+#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;
+ props = p1->data;
+ }
+ 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..a4a2a58e9a7f
--- /dev/null
+++ b/crypto/ffc/ffc_key_validate.c
@@ -0,0 +1,124 @@
+/*
+ * 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 1;
+ }
+
+ 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;
+ /* 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;
+ 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 (*ret == 0 && 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;
+ }
+
+ 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..3536efd1ad85
--- /dev/null
+++ b/crypto/ffc/ffc_params.c
@@ -0,0 +1,324 @@
+/*
+ * 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 <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;
+
+ dst->mdname = src->mdname;
+ dst->mdprops = src->mdprops;
+ 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..c1fe9df5d02f
--- /dev/null
+++ b/crypto/http/http_client.c
@@ -0,0 +1,1449 @@
+/*
+ * Copyright 2001-2025 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 optional port) must be given if and only if
+ * a plain HTTP proxy is used and |path| does not begin with 'http://'.
+ */
+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 (abs_path) */
+ if (path == NULL) {
+ path = "/";
+ } else if (HAS_PREFIX(path, "http://")) { /* absoluteURI for proxy use */
+ if (server != NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ } else 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);
+ return 0;
+ }
+ 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);
+ return 0;
+ }
+ 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
+
+static const char *explict_or_default_port(const char *hostserv, const char *port, int use_ssl)
+{
+ if (port == NULL) {
+ char *service = NULL;
+
+ if (!BIO_parse_hostserv(hostserv, NULL, &service, BIO_PARSE_PRIO_HOST))
+ return NULL;
+ if (service == NULL) /* implicit port */
+ port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
+ OPENSSL_free(service);
+ } /* otherwise take the explicitly given port */
+ return port;
+}
+
+/* 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;
+ }
+
+ port = explict_or_default_port(host, port, use_ssl);
+
+ 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;
+ 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;
+ int n_redirs = 0;
+ char *host;
+ char *port;
+ char *path;
+ int use_ssl;
+ 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 (;;) {
+ char *redirection_url;
+ OSSL_HTTP_REQ_CTX *rctx;
+
+ 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:
+ redirection_url = NULL;
+ 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);
+ rctx = NULL;
+ } 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..9c41f57541d7
--- /dev/null
+++ b/crypto/http/http_lib.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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>
+#ifndef OPENSSL_NO_SOCK
+# include "../bio/bio_local.h" /* for NI_MAXHOST */
+#endif
+#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() */
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 255
+#endif
+#include "crypto/ctype.h" /* for ossl_isspace() */
+
+static void init_pstring(char **pstr)
+{
+ if (pstr != NULL) {
+ *pstr = NULL;
+ }
+}
+
+static void init_pint(int *pint)
+{
+ if (pint != NULL) {
+ *pint = 0;
+ }
+}
+
+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_pint(pport_num);
+ 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) <= 0 || 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;
+ char host[NI_MAXHOST];
+
+ if (!ossl_assert(server != NULL))
+ return 0;
+ sl = strlen(server);
+ if (sl >= 2 && sl < sizeof(host) + 2 && server[0] == '[' && server[sl - 1] == ']') {
+ /* strip leading '[' and trailing ']' from escaped IPv6 address */
+ sl -= 2;
+ strncpy(host, server + 1, sl);
+ server = host;
+ }
+
+ /*
+ * 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 = ossl_safe_getenv("no_proxy");
+ if (no_proxy == NULL)
+ no_proxy = ossl_safe_getenv(OPENSSL_NO_PROXY);
+
+ if (no_proxy != NULL)
+ found = strstr(no_proxy, server);
+ while (found != NULL
+ && ((found != no_proxy && !ossl_isspace(found[-1]) && found[-1] != ',')
+ || (found[sl] != '\0' && !ossl_isspace(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 = ossl_safe_getenv(use_ssl ? "https_proxy" : "http_proxy");
+ if (proxy == NULL)
+ proxy = ossl_safe_getenv(use_ssl ? OPENSSL_HTTPS_PROXY : OPENSSL_HTTP_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..659a660eeced 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -1,12 +1,15 @@
/*
- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
}
@@ -128,17 +97,19 @@ static int win32atexit(void)
DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit)
{
-#ifdef OPENSSL_INIT_DEBUG
+#ifndef OPENSSL_NO_ATEXIT
+# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_register_atexit()\n");
-#endif
-#ifndef OPENSSL_SYS_UEFI
-# ifdef _WIN32
+# endif
+# ifndef OPENSSL_SYS_UEFI
+# if defined(_WIN32) && !defined(__BORLANDC__)
/* We use _onexit() in preference because it gets called on DLL unload */
if (_onexit(win32atexit) == NULL)
return 0;
-# else
+# else
if (atexit(OPENSSL_cleanup) != 0)
return 0;
+# endif
# endif
#endif
@@ -158,9 +129,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 +143,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 +162,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 +188,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 +209,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 +230,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 +248,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 +272,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 +283,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 +299,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 +326,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 +335,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 +343,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 +365,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 +376,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 +463,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 +508,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 +578,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 +611,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 +620,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 +648,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 +661,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 +688,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 +720,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..a01cfa725e38 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.
+ * 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
@@ -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;
@@ -269,18 +266,16 @@ static void contract(OPENSSL_LHASH *lh)
if (n == NULL) {
/* fputs("realloc error in lhash",stderr); */
lh->error++;
- return;
+ } else {
+ lh->b = n;
}
- lh->num_contract_reallocs++;
lh->num_alloc_nodes /= 2;
lh->pmax /= 2;
lh->p = lh->pmax - 1;
- lh->b = n;
} else
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/evp/m_md5_sha1.c b/crypto/md5/md5_sha1.c
index eeec2b13e9ed..56defab163fa 100644
--- a/crypto/evp/m_md5_sha1.c
+++ b/crypto/md5/md5_sha1.c
@@ -1,67 +1,55 @@
/*
- * 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
*/
-#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>
+/*
+ * MD5 and SHA-1 low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
-struct md5_sha1_ctx {
- MD5_CTX md5;
- SHA_CTX sha1;
-};
+#include <string.h>
+#include "prov/md5_sha1.h"
+#include <openssl/evp.h>
-static int init(EVP_MD_CTX *ctx)
+int ossl_md5_sha1_init(MD5_SHA1_CTX *mctx)
{
- 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)
+int ossl_md5_sha1_update(MD5_SHA1_CTX *mctx, 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)
+int ossl_md5_sha1_final(unsigned char *md, MD5_SHA1_CTX *mctx)
{
- 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)
+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];
- struct md5_sha1_ctx *mctx;
if (cmd != EVP_CTRL_SSL3_MASTER_SECRET)
return -2;
- if (ctx == NULL)
+ if (mctx == 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;
@@ -70,7 +58,7 @@ static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms)
* with master secret and pad_1.
*/
- if (update(ctx, ms, mslen) <= 0)
+ if (ossl_md5_sha1_update(mctx, ms, mslen) <= 0)
return 0;
/* Set padtmp to pad_1 value */
@@ -90,10 +78,10 @@ static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms)
/* Reinitialise context */
- if (!init(ctx))
+ if (!ossl_md5_sha1_init(mctx))
return 0;
- if (update(ctx, ms, mslen) <= 0)
+ if (ossl_md5_sha1_update(mctx, ms, mslen) <= 0)
return 0;
/* Set padtmp to pad_2 value */
@@ -117,26 +105,4 @@ static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms)
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/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..34128616e270 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-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
@@ -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);
}
/*
@@ -113,6 +100,9 @@ void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount)
* or 100;100@25;0
* This means 100 mallocs succeed, then next 100 fail 25% of the time, and
* all remaining (count is zero) succeed.
+ * The failure percentge can have 2 digits after the comma. For example:
+ * 0@0.01
+ * This means 0.01% of all allocations will fail.
*/
static void parseit(void)
{
@@ -125,26 +115,27 @@ static void parseit(void)
/* Get the count (atol will stop at the @ if there), and percentage */
md_count = atol(md_failstring);
atsign = strchr(md_failstring, '@');
- md_fail_percent = atsign == NULL ? 0 : atoi(atsign + 1);
+ md_fail_percent = atsign == NULL ? 0 : (int)(atof(atsign + 1) * 100 + 0.5);
if (semi != NULL)
md_failstring = semi;
}
/*
- * Windows doesn't have random(), but it has rand()
+ * Windows doesn't have random() and srandom(), but it has rand() and srand().
* Some rand() implementations aren't good, but we're not
* dealing with secure randomness here.
*/
# ifdef _WIN32
# define random() rand()
+# define srandom(seed) srand(seed)
# endif
/*
* See if the current malloc should fail.
*/
static int shouldfail(void)
{
- int roll = (int)(random() % 100);
+ int roll = (int)(random() % 10000);
int shoulditfail = roll < md_fail_percent;
# ifndef _WIN32
/* suppressed on Windows as POSIX-like file descriptors are non-inheritable */
@@ -158,14 +149,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
@@ -186,15 +169,15 @@ void ossl_malloc_setup_failures(void)
parseit();
if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL)
md_tracefd = atoi(cp);
+ if ((cp = getenv("OPENSSL_MALLOC_SEED")) != NULL)
+ srandom(atoi(cp));
}
#endif
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,39 +192,27 @@ 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;
- FAILTEST();
+ ret = CRYPTO_malloc(num, file, line);
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();
if (str == NULL)
return CRYPTO_malloc(num, file, line);
@@ -250,19 +221,8 @@ 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
+ FAILTEST();
return realloc(str, num);
-
}
void *CRYPTO_clear_realloc(void *str, size_t old_len, size_t num,
@@ -295,22 +255,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 +271,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..5cdeedb8d127 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,47 @@ 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
- return secure_mem_used;
-#else
- return 0;
-#endif /* OPENSSL_SECURE_MEMORY */
+ size_t ret = 0;
+
+#ifndef OPENSSL_NO_SECURE_MEMORY
+ if (!CRYPTO_THREAD_read_lock(sec_malloc_lock))
+ return 0;
+
+ ret = secure_mem_used;
+
+ CRYPTO_THREAD_unlock(sec_malloc_lock);
+#endif /* OPENSSL_NO_SECURE_MEMORY */
+ return ret;
}
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 +265,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 +407,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 +488,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 +511,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 +528,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 +556,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 +580,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 +726,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..302b6f5a8ec8
--- /dev/null
+++ b/crypto/modes/asm/aes-gcm-armv8_64.pl
@@ -0,0 +1,6097 @@
+#! /usr/bin/env perl
+# 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
+
+#
+#========================================================================
+# 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 ($rk0s,$rk1s,$rk2s,$rk3s,$rk4s,$rk5s,$rk6s,$rk7s,$rk8s,$rk9s)=map("v$_.4s",(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
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk10_l, $rk10_h, [$cc, #160] @ load rk10
+#ifdef __AARCH64EB__
+ ror $rk10_l, $rk10_l, #32
+ ror $rk10_h, $rk10_h, #32
+#endif
+ 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
+
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
+ 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
+#ifndef __AARCH64EB__
+ ext $h4b, $h4b, $h4b, #8
+#endif
+ 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
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
+
+ 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
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
+
+ add $rctr32w, $rctr32w, #1 @ CTR block 3
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
+ ext $h3b, $h3b, $h3b, #8
+#endif
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
+ ext $h1b, $h1b, $h1b, #8
+#endif
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
+
+ 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
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ld1 {$rk7s}, [$cc], #16 @ 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
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
+ ext $h2b, $h2b, $h2b, #8
+#endif
+
+ 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
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
+
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
+ ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 1 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifndef __AARCH64EB__
+ rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk10_l, $rk10_h, [$cc, #160] @ load rk10
+#ifdef __AARCH64EB__
+ ror $rk10_h, $rk10_h, 32
+ ror $rk10_l, $rk10_l, 32
+#endif
+ sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
+ ld1 {$rk0s}, [$cc], #16 @ 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
+#ifndef __AARCH64EB__
+ ext $h2b, $h2b, $h2b, #8
+#endif
+ lsr $rctr32x, $ctr96_t32x, #32
+ fmov $ctr2d, $ctr96_b64x @ CTR block 2
+
+ ld1 {$rk1s}, [$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
+ ld1 {$rk2s}, [$cc], #16 @ 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
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
+
+ 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
+
+ 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
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
+
+ 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
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
+
+ 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
+#ifndef __AARCH64EB__
+ ext $h3b, $h3b, $h3b, #8
+#endif
+ aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
+
+ 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
+#ifndef __AARCH64EB__
+ ext $h1b, $h1b, $h1b, #8
+#endif
+ 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
+#ifndef __AARCH64EB__
+ ext $h4b, $h4b, $h4b, #8
+#endif
+ 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
+
+ ld1 {$res0b, $res1b}, [$input_ptr], #32 @ AES block 0 - load ciphertext; AES block 1 - load ciphertext
+
+ eor $ctr1b, $res1b, $ctr1b @ AES block 1 - result
+ ld1 {$res2b}, [$input_ptr], #16 @ 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
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 3 - load ciphertext
+
+ rev64 $res1b, $res1b @ GHASH block 1
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
+ eor $output_l0, $output_l0, $rk10_l @ AES block 0 - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ eor $ctr2b, $res2b, $ctr2b @ AES block 2 - result
+
+ eor $output_h0, $output_h0, $rk10_h @ AES block 0 - round 10 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
+ 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
+ ld1 {$res0b}, [$input_ptr], #16 @ AES block 4k+3 - 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
+ ld1 {$res1b}, [$input_ptr], #16 @ AES block 4k+4 - 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
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 4k+5 - 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
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 4k+6 - load ciphertext
+
+ aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
+
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ .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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ .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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ eor $output_l0, $output_l0, $rk10_l @ AES final block - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+
+#ifndef __AARCH64EB__
+ rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
+
+ 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 ($rk0s,$rk1s,$rk2s,$rk3s,$rk4s,$rk5s,$rk6s,$rk7s,$rk8s,$rk9s,$rk10s,$rk11s)=map("v$_.4s",(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
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk12_l, $rk12_h, [$cc, #192] @ load rk12
+#ifdef __AARCH64EB__
+ ror $rk12_l, $rk12_l, #32
+ ror $rk12_h, $rk12_h, #32
+#endif
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
+
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
+
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
+
+ lsr $rctr32x, $ctr96_t32x, #32
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
+ orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
+
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
+ 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
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
+
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
+
+ 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
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
+ ext $h4b, $h4b, $h4b, #8
+#endif
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
+ ld1 {$rk10s}, [$cc], #16 @ load rk10
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
+ ext $h1b, $h1b, $h1b, #8
+#endif
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+ ld1 {$rk11s}, [$cc], #16 @ load rk11
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
+ ext $h3b, $h3b, $h3b, #8
+#endif
+ 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
+#ifndef __AARCH64EB__
+ ext $h2b, $h2b, $h2b, #8
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
+ ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 1 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifndef __AARCH64EB__
+ rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk12_l, $rk12_h, [$cc, #192] @ load rk12
+#ifdef __AARCH64EB__
+ ror $rk12_l, $rk12_l, #32
+ ror $rk12_h, $rk12_h, #32
+#endif
+ ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
+
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
+
+ lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
+ mov $len, $main_end_input_ptr
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
+
+ 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
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
+
+ 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
+ ld1 {$rk3s}, [$cc], #16 @ 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
+
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
+ ext $h4b, $h4b, $h4b, #8
+#endif
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
+ ext $h2b, $h2b, $h2b, #8
+#endif
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
+ ext $h3b, $h3b, $h3b, #8
+#endif
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
+ ext $h1b, $h1b, $h1b, #8
+#endif
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
+
+ aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
+
+ 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
+ ld1 {$rk10s}, [$cc], #16 @ load rk10
+
+ 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
+ ld1 {$rk11s}, [$cc], #16 @ load rk11
+
+ 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
+
+ ld1 {$res0b, $res1b}, [$input_ptr], #32 @ AES block 0,1 - load ciphertext
+
+ eor $ctr1b, $res1b, $ctr1b @ AES block 1 - result
+
+ eor $ctr0b, $res0b, $ctr0b @ AES block 0 - result
+ rev $ctr32w, $rctr32w @ CTR block 4
+ ld1 {$res2b, $res3b}, [$input_ptr], #32 @ AES block 2,3 - 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
+
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ rev $ctr32w, $rctr32w @ CTR block 6
+ eor $output_h0, $output_h0, $rk12_h @ AES block 0 - round 12 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
+ 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
+ ld1 {$res0b}, [$input_ptr], #16 @ AES block 4k+4 - 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
+ ld1 {$res1b}, [$input_ptr], #16 @ AES block 4k+5 - load ciphertext
+ eor $output_l3, $output_l3, $rk12_l @ AES block 4k+3 - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
+ 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
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 4k+6 - load ciphertext
+
+ aese $ctr1b, $rk11 @ AES block 4k+5 - round 11
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 4k+7 - 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
+
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
+ eor $output_h0, $output_h0, $rk12_h @ AES block 4k+4 - round 12 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ eor $output_l0, $output_l0, $rk12_l @ AES block 4k+4 - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ .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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ eor $output_l0, $output_l0, $rk12_l @ AES final-1 block - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ eor $output_l0, $output_l0, $rk12_l @ AES final block - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifndef __AARCH64EB__
+ rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
+
+ 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 ($rk0s,$rk1s,$rk2s,$rk3s,$rk4s,$rk5s,$rk6s,$rk7s,$rk8s,$rk9s,$rk10s,$rk11s,$rk12s,$rk13s)=map("v$_.4s",(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
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk14_l, $rk14_h, [$cc, #224] @ load rk14
+#ifdef __AARCH64EB__
+ ror $rk14_l, $rk14_l, #32
+ ror $rk14_h, $rk14_h, #32
+#endif
+ 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
+
+ ld1 {$rk0s}, [$cc], #16 @ 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 {$rk1s}, [$cc], #16 @ load rk1
+ 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
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
+
+ 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
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
+
+ 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
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
+
+ aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
+ ext $h3b, $h3b, $h3b, #8
+#endif
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
+
+ aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
+
+ aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
+ ext $h2b, $h2b, $h2b, #8
+#endif
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
+
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
+ ext $h4b, $h4b, $h4b, #8
+#endif
+ aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
+ ld1 {$rk10s}, [$cc], #16 @ load rk10
+
+ aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
+ ld1 {$rk11s}, [$cc], #16 @ load rk11
+
+ 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
+
+ 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
+ ld1 {$rk12s}, [$cc], #16 @ load rk12
+
+ aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
+ ext $h1b, $h1b, $h1b, #8
+#endif
+ aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
+ ld1 {$rk13s}, [$cc], #16 @ load rk13
+
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
+ rev $ctr32w, $rctr32w @ CTR block 4
+ ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 0 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
+ ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
+ 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
+#ifndef __AARCH64EB__
+ rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
+
+ 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
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk14_l, $rk14_h, [$cc, #224] @ load rk14
+#ifdef __AARCH64EB__
+ ror $rk14_h, $rk14_h, #32
+ ror $rk14_l, $rk14_l, #32
+#endif
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
+ sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
+
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
+ 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
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
+
+ lsr $rctr32x, $ctr96_t32x, #32
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
+ orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
+
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
+ 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
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
+
+ fmov $ctr3.d[1], $ctr32x @ CTR block 3
+ add $rctr32w, $rctr32w, #1 @ CTR block 3
+
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
+
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
+
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
+
+ aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
+ ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
+ ext $h3b, $h3b, $h3b, #8
+#endif
+
+ aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
+ ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
+ ext $h4b, $h4b, $h4b, #8
+#endif
+
+ aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
+ ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
+ ext $h2b, $h2b, $h2b, #8
+#endif
+
+ aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
+
+ aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
+
+ 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
+ ld1 {$rk10s}, [$cc], #16 @ load rk10
+
+ aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
+ ld1 {$rk11s}, [$cc], #16 @ load rk11
+
+ aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
+ ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
+ ext $h1b, $h1b, $h1b, #8
+#endif
+ aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
+ ld1 {$rk12s}, [$cc], #16 @ load rk12
+
+ 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
+ ld1 {$rk13s}, [$cc], #16 @ load rk13
+
+ 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
+
+ ld1 {$res0b, $res1b}, [$input_ptr], #32 @ AES block 0,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
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 2 - 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ eor $output_l0, $output_l0, $rk14_l @ AES block 0 - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 0 - store result
+ fmov $ctr1d, $ctr96_b64x @ CTR block 5
+
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 3 - load ciphertext
+
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
+ orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
+
+ eor $output_h1, $output_h1, $rk14_h @ AES block 1 - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
+ 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
+ ld1 {$res0b}, [$input_ptr], #16 @ 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
+ ld1 {$res1b}, [$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
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 4k+6 - load ciphertext
+
+ aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 4k+7 - 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
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ eor $output_h0, $output_h0, $rk14_h @ AES block 4k+4 - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
+
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
+
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+
+ eor $output_h0, $output_h0, $rk14_h @ AES block 4k+4 - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ .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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ .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
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
+ 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
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
+ .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
+
+#ifndef __AARCH64EB__
+ rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
+
+ 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";
+ }
+ s/__AARCH64E([BL])__/__ARME$1__/go;
+ 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-alpha.pl b/crypto/modes/asm/ghash-alpha.pl
new file mode 100644
index 000000000000..c350e9015550
--- /dev/null
+++ b/crypto/modes/asm/ghash-alpha.pl
@@ -0,0 +1,467 @@
+#! /usr/bin/env perl
+# Copyright 2010-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/.
+# ====================================================================
+#
+# March 2010
+#
+# The module implements "4-bit" GCM GHASH function and underlying
+# single multiplication operation in GF(2^128). "4-bit" means that it
+# uses 256 bytes per-key table [+128 bytes shared table]. Even though
+# loops are aggressively modulo-scheduled in respect to references to
+# Htbl and Z.hi updates for 8 cycles per byte, measured performance is
+# ~12 cycles per processed byte on 21264 CPU. It seems to be a dynamic
+# scheduling "glitch," because uprofile(1) indicates uniform sample
+# distribution, as if all instruction bundles execute in 1.5 cycles.
+# Meaning that it could have been even faster, yet 12 cycles is ~60%
+# better than gcc-generated code and ~80% than code generated by vendor
+# compiler.
+
+$cnt="v0"; # $0
+$t0="t0";
+$t1="t1";
+$t2="t2";
+$Thi0="t3"; # $4
+$Tlo0="t4";
+$Thi1="t5";
+$Tlo1="t6";
+$rem="t7"; # $8
+#################
+$Xi="a0"; # $16, input argument block
+$Htbl="a1";
+$inp="a2";
+$len="a3";
+$nlo="a4"; # $20
+$nhi="a5";
+$Zhi="t8";
+$Zlo="t9";
+$Xhi="t10"; # $24
+$Xlo="t11";
+$remp="t12";
+$rem_4bit="AT"; # $28
+
+{ my $N;
+ sub loop() {
+
+ $N++;
+$code.=<<___;
+.align 4
+ extbl $Xlo,7,$nlo
+ and $nlo,0xf0,$nhi
+ sll $nlo,4,$nlo
+ and $nlo,0xf0,$nlo
+
+ addq $nlo,$Htbl,$nlo
+ ldq $Zlo,8($nlo)
+ addq $nhi,$Htbl,$nhi
+ ldq $Zhi,0($nlo)
+
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ lda $cnt,6(zero)
+ extbl $Xlo,6,$nlo
+
+ ldq $Tlo1,8($nhi)
+ s8addq $remp,$rem_4bit,$remp
+ ldq $Thi1,0($nhi)
+ srl $Zlo,4,$Zlo
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ xor $t0,$Zlo,$Zlo
+ and $nlo,0xf0,$nhi
+
+ xor $Tlo1,$Zlo,$Zlo
+ sll $nlo,4,$nlo
+ xor $Thi1,$Zhi,$Zhi
+ and $nlo,0xf0,$nlo
+
+ addq $nlo,$Htbl,$nlo
+ ldq $Tlo0,8($nlo)
+ addq $nhi,$Htbl,$nhi
+ ldq $Thi0,0($nlo)
+
+.Looplo$N:
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ subq $cnt,1,$cnt
+ srl $Zlo,4,$Zlo
+
+ ldq $Tlo1,8($nhi)
+ xor $rem,$Zhi,$Zhi
+ ldq $Thi1,0($nhi)
+ s8addq $remp,$rem_4bit,$remp
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ xor $t0,$Zlo,$Zlo
+ extbl $Xlo,$cnt,$nlo
+
+ and $nlo,0xf0,$nhi
+ xor $Thi0,$Zhi,$Zhi
+ xor $Tlo0,$Zlo,$Zlo
+ sll $nlo,4,$nlo
+
+
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ and $nlo,0xf0,$nlo
+ srl $Zlo,4,$Zlo
+
+ s8addq $remp,$rem_4bit,$remp
+ xor $rem,$Zhi,$Zhi
+ addq $nlo,$Htbl,$nlo
+ addq $nhi,$Htbl,$nhi
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ ldq $Tlo0,8($nlo)
+ xor $t0,$Zlo,$Zlo
+
+ xor $Tlo1,$Zlo,$Zlo
+ xor $Thi1,$Zhi,$Zhi
+ ldq $Thi0,0($nlo)
+ bne $cnt,.Looplo$N
+
+
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ lda $cnt,7(zero)
+ srl $Zlo,4,$Zlo
+
+ ldq $Tlo1,8($nhi)
+ xor $rem,$Zhi,$Zhi
+ ldq $Thi1,0($nhi)
+ s8addq $remp,$rem_4bit,$remp
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ xor $t0,$Zlo,$Zlo
+ extbl $Xhi,$cnt,$nlo
+
+ and $nlo,0xf0,$nhi
+ xor $Thi0,$Zhi,$Zhi
+ xor $Tlo0,$Zlo,$Zlo
+ sll $nlo,4,$nlo
+
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ and $nlo,0xf0,$nlo
+ srl $Zlo,4,$Zlo
+
+ s8addq $remp,$rem_4bit,$remp
+ xor $rem,$Zhi,$Zhi
+ addq $nlo,$Htbl,$nlo
+ addq $nhi,$Htbl,$nhi
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ ldq $Tlo0,8($nlo)
+ xor $t0,$Zlo,$Zlo
+
+ xor $Tlo1,$Zlo,$Zlo
+ xor $Thi1,$Zhi,$Zhi
+ ldq $Thi0,0($nlo)
+ unop
+
+
+.Loophi$N:
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ subq $cnt,1,$cnt
+ srl $Zlo,4,$Zlo
+
+ ldq $Tlo1,8($nhi)
+ xor $rem,$Zhi,$Zhi
+ ldq $Thi1,0($nhi)
+ s8addq $remp,$rem_4bit,$remp
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ xor $t0,$Zlo,$Zlo
+ extbl $Xhi,$cnt,$nlo
+
+ and $nlo,0xf0,$nhi
+ xor $Thi0,$Zhi,$Zhi
+ xor $Tlo0,$Zlo,$Zlo
+ sll $nlo,4,$nlo
+
+
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ and $nlo,0xf0,$nlo
+ srl $Zlo,4,$Zlo
+
+ s8addq $remp,$rem_4bit,$remp
+ xor $rem,$Zhi,$Zhi
+ addq $nlo,$Htbl,$nlo
+ addq $nhi,$Htbl,$nhi
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ ldq $Tlo0,8($nlo)
+ xor $t0,$Zlo,$Zlo
+
+ xor $Tlo1,$Zlo,$Zlo
+ xor $Thi1,$Zhi,$Zhi
+ ldq $Thi0,0($nlo)
+ bne $cnt,.Loophi$N
+
+
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ srl $Zlo,4,$Zlo
+
+ ldq $Tlo1,8($nhi)
+ xor $rem,$Zhi,$Zhi
+ ldq $Thi1,0($nhi)
+ s8addq $remp,$rem_4bit,$remp
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ xor $t0,$Zlo,$Zlo
+
+ xor $Tlo0,$Zlo,$Zlo
+ xor $Thi0,$Zhi,$Zhi
+
+ and $Zlo,0x0f,$remp
+ sll $Zhi,60,$t0
+ srl $Zlo,4,$Zlo
+
+ s8addq $remp,$rem_4bit,$remp
+ xor $rem,$Zhi,$Zhi
+
+ ldq $rem,0($remp)
+ srl $Zhi,4,$Zhi
+ xor $Tlo1,$Zlo,$Zlo
+ xor $Thi1,$Zhi,$Zhi
+ xor $t0,$Zlo,$Zlo
+ xor $rem,$Zhi,$Zhi
+___
+}}
+
+$code=<<___;
+#ifdef __linux__
+#include <asm/regdef.h>
+#else
+#include <asm.h>
+#include <regdef.h>
+#endif
+
+.text
+
+.set noat
+.set noreorder
+.globl gcm_gmult_4bit
+.align 4
+.ent gcm_gmult_4bit
+gcm_gmult_4bit:
+ .frame sp,0,ra
+ .prologue 0
+
+ ldq $Xlo,8($Xi)
+ ldq $Xhi,0($Xi)
+
+ bsr $t0,picmeup
+ nop
+___
+
+ &loop();
+
+$code.=<<___;
+ srl $Zlo,24,$t0 # byte swap
+ srl $Zlo,8,$t1
+
+ sll $Zlo,8,$t2
+ sll $Zlo,24,$Zlo
+ zapnot $t0,0x11,$t0
+ zapnot $t1,0x22,$t1
+
+ zapnot $Zlo,0x88,$Zlo
+ or $t0,$t1,$t0
+ zapnot $t2,0x44,$t2
+
+ or $Zlo,$t0,$Zlo
+ srl $Zhi,24,$t0
+ srl $Zhi,8,$t1
+
+ or $Zlo,$t2,$Zlo
+ sll $Zhi,8,$t2
+ sll $Zhi,24,$Zhi
+
+ srl $Zlo,32,$Xlo
+ sll $Zlo,32,$Zlo
+
+ zapnot $t0,0x11,$t0
+ zapnot $t1,0x22,$t1
+ or $Zlo,$Xlo,$Xlo
+
+ zapnot $Zhi,0x88,$Zhi
+ or $t0,$t1,$t0
+ zapnot $t2,0x44,$t2
+
+ or $Zhi,$t0,$Zhi
+ or $Zhi,$t2,$Zhi
+
+ srl $Zhi,32,$Xhi
+ sll $Zhi,32,$Zhi
+
+ or $Zhi,$Xhi,$Xhi
+ stq $Xlo,8($Xi)
+ stq $Xhi,0($Xi)
+
+ ret (ra)
+.end gcm_gmult_4bit
+___
+
+$inhi="s0";
+$inlo="s1";
+
+$code.=<<___;
+.globl gcm_ghash_4bit
+.align 4
+.ent gcm_ghash_4bit
+gcm_ghash_4bit:
+ lda sp,-32(sp)
+ stq ra,0(sp)
+ stq s0,8(sp)
+ stq s1,16(sp)
+ .mask 0x04000600,-32
+ .frame sp,32,ra
+ .prologue 0
+
+ ldq_u $inhi,0($inp)
+ ldq_u $Thi0,7($inp)
+ ldq_u $inlo,8($inp)
+ ldq_u $Tlo0,15($inp)
+ ldq $Xhi,0($Xi)
+ ldq $Xlo,8($Xi)
+
+ bsr $t0,picmeup
+ nop
+
+.Louter:
+ extql $inhi,$inp,$inhi
+ extqh $Thi0,$inp,$Thi0
+ or $inhi,$Thi0,$inhi
+ lda $inp,16($inp)
+
+ extql $inlo,$inp,$inlo
+ extqh $Tlo0,$inp,$Tlo0
+ or $inlo,$Tlo0,$inlo
+ subq $len,16,$len
+
+ xor $Xlo,$inlo,$Xlo
+ xor $Xhi,$inhi,$Xhi
+___
+
+ &loop();
+
+$code.=<<___;
+ srl $Zlo,24,$t0 # byte swap
+ srl $Zlo,8,$t1
+
+ sll $Zlo,8,$t2
+ sll $Zlo,24,$Zlo
+ zapnot $t0,0x11,$t0
+ zapnot $t1,0x22,$t1
+
+ zapnot $Zlo,0x88,$Zlo
+ or $t0,$t1,$t0
+ zapnot $t2,0x44,$t2
+
+ or $Zlo,$t0,$Zlo
+ srl $Zhi,24,$t0
+ srl $Zhi,8,$t1
+
+ or $Zlo,$t2,$Zlo
+ sll $Zhi,8,$t2
+ sll $Zhi,24,$Zhi
+
+ srl $Zlo,32,$Xlo
+ sll $Zlo,32,$Zlo
+ beq $len,.Ldone
+
+ zapnot $t0,0x11,$t0
+ zapnot $t1,0x22,$t1
+ or $Zlo,$Xlo,$Xlo
+ ldq_u $inhi,0($inp)
+
+ zapnot $Zhi,0x88,$Zhi
+ or $t0,$t1,$t0
+ zapnot $t2,0x44,$t2
+ ldq_u $Thi0,7($inp)
+
+ or $Zhi,$t0,$Zhi
+ or $Zhi,$t2,$Zhi
+ ldq_u $inlo,8($inp)
+ ldq_u $Tlo0,15($inp)
+
+ srl $Zhi,32,$Xhi
+ sll $Zhi,32,$Zhi
+
+ or $Zhi,$Xhi,$Xhi
+ br zero,.Louter
+
+.Ldone:
+ zapnot $t0,0x11,$t0
+ zapnot $t1,0x22,$t1
+ or $Zlo,$Xlo,$Xlo
+
+ zapnot $Zhi,0x88,$Zhi
+ or $t0,$t1,$t0
+ zapnot $t2,0x44,$t2
+
+ or $Zhi,$t0,$Zhi
+ or $Zhi,$t2,$Zhi
+
+ srl $Zhi,32,$Xhi
+ sll $Zhi,32,$Zhi
+
+ or $Zhi,$Xhi,$Xhi
+
+ stq $Xlo,8($Xi)
+ stq $Xhi,0($Xi)
+
+ .set noreorder
+ /*ldq ra,0(sp)*/
+ ldq s0,8(sp)
+ ldq s1,16(sp)
+ lda sp,32(sp)
+ ret (ra)
+.end gcm_ghash_4bit
+
+.align 4
+.ent picmeup
+picmeup:
+ .frame sp,0,$t0
+ .prologue 0
+ br $rem_4bit,.Lpic
+.Lpic: lda $rem_4bit,12($rem_4bit)
+ ret ($t0)
+.end picmeup
+ nop
+rem_4bit:
+ .long 0,0x0000<<16, 0,0x1C20<<16, 0,0x3840<<16, 0,0x2460<<16
+ .long 0,0x7080<<16, 0,0x6CA0<<16, 0,0x48C0<<16, 0,0x54E0<<16
+ .long 0,0xE100<<16, 0,0xFD20<<16, 0,0xD940<<16, 0,0xC560<<16
+ .long 0,0x9180<<16, 0,0x8DA0<<16, 0,0xA9C0<<16, 0,0xB5E0<<16
+.ascii "GHASH for Alpha, CRYPTOGAMS by <appro\@openssl.org>"
+.align 4
+
+___
+$output=pop and open STDOUT,">$output";
+print $code;
+close STDOUT or die "error closing STDOUT: $!";
+
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..b3d94041729e 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.
+# 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
@@ -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
___
################################################################################
@@ -732,6 +744,9 @@ if ($flavour =~ /64/) { ######## 64-bit code
s/\.[uisp]?64//o and s/\.16b/\.2d/go;
s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o;
+ # Switch preprocessor checks to aarch64 versions.
+ s/__ARME([BL])__/__AARCH64E$1__/go;
+
print $_,"\n";
}
} else { ######## 32-bit code
@@ -752,7 +767,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 +782,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..a6598171535e 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the 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,165 @@ 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);
- }
+ ++len;
+ 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 < 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 && buflen > 0)
+ --q;
+ *q = CH_ZERO;
+
#ifdef CHARSET_EBCDIC
- ebcdic2ascii(tmp, tmp, q - tmp - 1);
+ ebcdic2ascii(str, str, q - str);
#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 +343,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..dc501cbb8b22 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.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,7 +62,7 @@ static unsigned long added_obj_hash(const ADDED_OBJ *ca)
a = ca->obj;
switch (ca->type) {
case ADDED_DATA:
- ret = a->length << 20L;
+ ret = (unsigned long)a->length << 20UL;
p = (unsigned char *)a->data;
for (i = 0; i < a->length; i++)
ret ^= p[i] << ((i * 3) % 24);
@@ -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;
}
@@ -428,6 +443,25 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
first = 1;
bl = NULL;
+ /*
+ * RFC 2578 (STD 58) says this about OBJECT IDENTIFIERs:
+ *
+ * > 3.5. OBJECT IDENTIFIER values
+ * >
+ * > An OBJECT IDENTIFIER value is an ordered list of non-negative
+ * > numbers. For the SMIv2, each number in the list is referred to as a
+ * > sub-identifier, there are at most 128 sub-identifiers in a value,
+ * > and each sub-identifier has a maximum value of 2^32-1 (4294967295
+ * > decimal).
+ *
+ * So a legitimate OID according to this RFC is at most (32 * 128 / 7),
+ * i.e. 586 bytes long.
+ *
+ * Ref: https://datatracker.ietf.org/doc/html/rfc2578#section-3.5
+ */
+ if (len > 586)
+ goto err;
+
while (len > 0) {
l = 0;
use_bn = 0;
@@ -545,6 +579,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 +603,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 +626,33 @@ 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;
+ char *p1;
+
for (i = 0; i < num; ++i) {
- p = &(base[i * size]);
- c = (*cmp) (key, p);
- if (c == 0 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
- return p;
+ p1 = &(base_[i * size]);
+ c = (*cmp) (key, p1);
+ if (c == 0
+ || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
+ return p1;
}
}
#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 +717,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 +728,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..56537e676b77
--- /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);
+ 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);
+ 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..5de06cc7ed68
--- /dev/null
+++ b/crypto/param_build_set.c
@@ -0,0 +1,122 @@
+/*
+ * 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
+ */
+
+/*
+ * 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;
+ const BIGNUM *bn;
+
+ if (bld != NULL) {
+ for (i = 0; i < sz && names[i] != NULL; ++i) {
+ bn = sk_BIGNUM_const_value(stk, i);
+ if (bn != NULL && !OSSL_PARAM_BLD_push_BN(bld, names[i], bn))
+ return 0;
+ }
+ return 1;
+ }
+
+ for (i = 0; i < sz && names[i] != NULL; ++i) {
+ bn = sk_BIGNUM_const_value(stk, i);
+ p = OSSL_PARAM_locate(params, names[i]);
+ if (p != NULL && bn != NULL) {
+ if (!OSSL_PARAM_set_BN(p, bn))
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/crypto/params.c b/crypto/params.c
new file mode 100644
index 000000000000..4d85b5943c71
--- /dev/null
+++ b/crypto/params.c
@@ -0,0 +1,1319 @@
+/*
+ * 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"
+
+#ifndef OPENSSL_SYS_UEFI
+/*
+ * 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;
+}
+#endif
+
+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)
+{
+ 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) {
+#ifndef OPENSSL_SYS_UEFI
+ double d;
+
+ 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;
+ }
+#endif
+ }
+ 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) {
+#ifndef OPENSSL_SYS_UEFI
+ 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;
+ }
+#endif
+ }
+ 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)
+{
+ 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) {
+#ifndef OPENSSL_SYS_UEFI
+ double d;
+
+ 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;
+ }
+#endif
+ }
+ 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) {
+#ifndef OPENSSL_SYS_UEFI
+ 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;
+ }
+#endif
+ }
+ 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)
+{
+ 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) {
+#ifndef OPENSSL_SYS_UEFI
+ double d;
+
+ 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;
+ }
+#endif
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_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(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) {
+#ifndef OPENSSL_SYS_UEFI
+ uint64_t u64;
+
+ 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;
+ }
+#endif
+ }
+ 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)
+{
+ 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) {
+#ifndef OPENSSL_SYS_UEFI
+ double d;
+
+ 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;
+ }
+#endif
+ }
+ 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) {
+#ifndef OPENSSL_SYS_UEFI
+ 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;
+ }
+#endif
+ }
+ 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);
+}
+
+#ifndef OPENSSL_SYS_UEFI
+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));
+}
+#endif
+
+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..f2c9537be8b1
--- /dev/null
+++ b/crypto/params_dup.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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) {
+ while (*p2cur != NULL) {
+ *dst++ = **p2cur;
+ p2cur++;
+ }
+ break;
+ }
+ /* If list2 is finished just tack list1 onto the end */
+ if (*p2cur == NULL) {
+ while (*p1cur != NULL) {
+ *dst++ = **p1cur;
+ p1cur++;
+ }
+ 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..a323bf2616ad
--- /dev/null
+++ b/crypto/params_from_text.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2019-2024 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) {
+ size_t hexdigits = strlen(value);
+ if ((hexdigits % 2) != 0) {
+ /* We don't accept an odd number of hex digits */
+ ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_ODD_NUMBER_OF_DIGITS);
+ return 0;
+ }
+ *buf_n = hexdigits >> 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..6e84f0afd05d 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,
@@ -116,29 +173,30 @@ EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
X509_SIG *p8 = NULL;
int klen;
EVP_PKEY *ret;
- char psbuf[PEM_BUFSIZE];
+ char psbuf[PEM_BUFSIZE + 1]; /* reserve one byte at the end */
+
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);
+ if (klen < 0 || klen > PEM_BUFSIZE) {
+ 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..4deee46ce550 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-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 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,254 @@ 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
+static int no_password_cb(char *buf, int num, int rwflag, void *userdata)
+{
+ return -1;
+}
-#ifndef OPENSSL_NO_DH
+EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,
+ OSSL_LIB_CTX *libctx, const char *propq)
+{
+ /*
+ * PEM_read_bio_Parameters(_ex) should never ask for a password. Any attempt
+ * to get a password just fails.
+ */
+ return pem_read_bio_key(bp, x, no_password_cb, 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;
}
-# endif
+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;
+}
+
+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..38d570c79017 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.
+# 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
@@ -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
{
@@ -142,9 +159,8 @@ while(my $line=<>) {
}
{
- $line =~ s|(^[\.\w]+)\:\s*||;
- my $label = $1;
- if ($label) {
+ if ($line =~ s|(^[\.\w]+)\:\s*||) {
+ my $label = $1;
printf "%s:",($GLOBALS{$label} or $label);
}
}
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..3f24511c1a6b 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.
+# Copyright 2012-2025 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with 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,8 +46,8 @@ $::code.=<<___;
.align 32
${alg}${bits}_t4_cbc_encrypt:
save %sp, -$::frame, %sp
- cmp $len, 0
- be,pn $::size_t_cc, .L${bits}_cbc_enc_abort
+ cmp $len, 15
+ bleu,pn $::size_t_cc, .L${bits}_cbc_enc_abort
srln $len, 0, $len ! needed on v8+, "nop" on v9
sub $inp, $out, $blk_init ! $inp!=$out
___
@@ -264,8 +264,8 @@ $::code.=<<___;
.align 32
${alg}${bits}_t4_cbc_decrypt:
save %sp, -$::frame, %sp
- cmp $len, 0
- be,pn $::size_t_cc, .L${bits}_cbc_dec_abort
+ cmp $len, 15
+ bleu,pn $::size_t_cc, .L${bits}_cbc_dec_abort
srln $len, 0, $len ! needed on v8+, "nop" on v9
sub $inp, $out, $blk_init ! $inp!=$out
___
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..b2bf96cef01e 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,56 @@ 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 .*|Intel.*oneAPI .*)/)
+{
+ $gnuas=1;
+}
+elsif (`$ENV{CC} -V 2>/dev/null`
+ =~ /nvc .*/)
+{
+ $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 +1205,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 +1267,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..66dcf92ca11e 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,76 +75,111 @@ 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;
}
+
+ if (p7->d.data == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR);
+ return NULL;
+ }
+
return ASN1_item_unpack(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS));
}
/* 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,
+
+ if (p7->d.encrypted == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR);
+ return NULL;
+ }
+
+ 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 +192,31 @@ 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;
+ }
+
+ if (p12->authsafes->d.data == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR);
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..3c7d5ff97c52 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,12 @@
static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
PKCS12_SAFEBAG *bag);
+static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ X509 *cert,
+ const char *name,
+ int namelen,
+ unsigned char *keyid,
+ int keyidlen);
static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
{
@@ -28,9 +34,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;
@@ -39,23 +46,22 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
int i;
unsigned char keyid[EVP_MAX_MD_SIZE];
unsigned int keyidlen = 0;
+ int namelen = -1;
+ unsigned char *pkeyid = NULL;
+ int pkeyidlen = -1;
/* 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;
}
@@ -67,11 +73,16 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
}
if (cert) {
- bag = PKCS12_add_cert(&bags, cert);
- if (name && !PKCS12_add_friendlyname(bag, name, -1))
- goto err;
- if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
- goto err;
+ if (name == NULL)
+ name = (char *)X509_alias_get0(cert, &namelen);
+ if (keyidlen > 0) {
+ pkeyid = keyid;
+ pkeyidlen = keyidlen;
+ } else {
+ pkeyid = X509_keyid_get0(cert, &pkeyidlen);
+ }
+
+ bag = pkcs12_add_cert_bag(&bags, cert, name, namelen, pkeyid, pkeyidlen);
}
/* Add all other certificates */
@@ -80,14 +91,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 +122,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,30 +145,31 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
}
-PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
+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);
+}
+
+static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
+ X509 *cert,
+ const char *name,
+ int namelen,
+ unsigned char *keyid,
+ int keyidlen)
{
PKCS12_SAFEBAG *bag = NULL;
- char *name;
- int namelen = -1;
- unsigned char *keyid;
- int keyidlen = -1;
/* Add user certificate */
if ((bag = PKCS12_SAFEBAG_create_cert(cert)) == NULL)
goto err;
- /*
- * Use friendlyName and localKeyID in certificate. (if present)
- */
-
- name = (char *)X509_alias_get0(cert, &namelen);
-
- if (name && !PKCS12_add_friendlyname(bag, name, namelen))
+ if (name != NULL && !PKCS12_add_friendlyname(bag, name, namelen))
goto err;
- keyid = X509_keyid_get0(cert, &keyidlen);
-
- if (keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
+ if (keyid != NULL && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
goto err;
if (!pkcs12_add_bag(pbags, bag))
@@ -166,12 +180,28 @@ PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
err:
PKCS12_SAFEBAG_free(bag);
return NULL;
+}
+
+PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
+{
+ char *name = NULL;
+ int namelen = -1;
+ unsigned char *keyid = NULL;
+ int keyidlen = -1;
+ /*
+ * Use friendlyName and localKeyID in certificate. (if present)
+ */
+ name = (char *)X509_alias_get0(cert, &namelen);
+ keyid = X509_keyid_get0(cert, &keyidlen);
+
+ return pkcs12_add_cert_bag(pbags, cert, name, namelen, keyid, keyidlen);
}
-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;
@@ -180,42 +210,73 @@ PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
/* Make a PKCS#8 structure */
if ((p8 = EVP_PKEY2PKCS8(key)) == NULL)
goto err;
- if (key_usage && !PKCS8_add_keyusage(p8, key_usage))
+ if (key_usage && !PKCS8_add_keyusage(p8, key_usage)) {
+ PKCS8_PRIV_KEY_INFO_free(p8);
goto err;
+ }
if (nid_key != -1) {
- bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(nid_key, pass, -1, NULL, 0,
- iter, p8);
- PKCS8_PRIV_KEY_INFO_free(p8);
- } else
+ /* This call does not take ownership of p8 */
+ bag = PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(nid_key, pass, -1, NULL, 0,
+ iter, p8, ctx, propq);
+ } else {
bag = PKCS12_SAFEBAG_create0_p8inf(p8);
+ if (bag != NULL)
+ p8 = NULL; /* bag takes ownership of p8 */
+ }
+ /* This does not need to be in the error path */
+ if (p8 != NULL)
+ PKCS8_PRIV_KEY_INFO_free(p8);
- if (!bag)
+ if (bag == NULL || !pkcs12_add_bag(pbags, bag))
+ goto err;
+
+ return bag;
+
+ err:
+ PKCS12_SAFEBAG_free(bag);
+ return NULL;
+
+}
+
+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(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
- int nid_safe, int iter, const char *pass)
+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 +288,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 +304,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 +338,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 +357,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..f8a6d33ddfae 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,85 @@ 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;
+ }
+
+ if (p12->authsafes->d.data == NULL) {
+ ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR);
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;
+
+ (void)ERR_set_mark();
+ 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) {
+ (void)ERR_clear_last_mark();
+ 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);
+ (void)ERR_pop_to_mark();
+
+ 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 +171,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 +189,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 +214,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 +251,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..dfcfcf6ae677 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
}
@@ -78,8 +77,9 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass)
bags = PKCS12_unpack_p7data(p7);
} else if (bagnid == NID_pkcs7_encrypted) {
bags = PKCS12_unpack_p7encdata(p7, oldpass, -1);
- if (!alg_get(p7->d.encrypted->enc_data->algorithm,
- &pbe_nid, &pbe_iter, &pbe_saltlen))
+ if (p7->d.encrypted == NULL
+ || !alg_get(p7->d.encrypted->enc_data->algorithm,
+ &pbe_nid, &pbe_iter, &pbe_saltlen))
goto err;
} else {
continue;
@@ -94,7 +94,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 +157,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 +175,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..80b128c30455 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,13 +23,17 @@ 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,
ASN1_ITEM_rptr(X509_ALGORS));
- return PKCS7_add_signed_attribute(si, NID_SMIMECapabilities,
- V_ASN1_SEQUENCE, seq);
+ if (!PKCS7_add_signed_attribute(si, NID_SMIMECapabilities,
+ V_ASN1_SEQUENCE, seq)) {
+ ASN1_STRING_free(seq);
+ return 0;
+ }
+ return 1;
}
STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si)
@@ -53,7 +57,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 +81,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;
@@ -95,13 +99,18 @@ 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);
+ ASN1_TIME *tmp = NULL;
+
+ if (t == NULL && (tmp = t = X509_gmtime_adj(NULL, 0)) == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE);
return 0;
}
- return PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime,
- V_ASN1_UTCTIME, t);
+ if (!PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime,
+ V_ASN1_UTCTIME, t)) {
+ ASN1_TIME_free(tmp);
+ return 0;
+ }
+ return 1;
}
int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si,
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
index f63fbc50ea60..e9de097da186 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the 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,26 @@ 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;
+ unsigned char *abuf = NULL;
+ 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 +1045,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);
}
@@ -993,7 +1073,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
sk = si->auth_attr;
if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) {
- unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
+ unsigned char md_dat[EVP_MAX_MD_SIZE];
unsigned int md_len;
int alen;
ASN1_OCTET_STRING *message_digest;
@@ -1002,49 +1082,59 @@ 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;
}
if (!EVP_VerifyUpdate(mdc_tmp, abuf, alen))
goto err;
-
- OPENSSL_free(abuf);
}
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:
+ OPENSSL_free(abuf);
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;
@@ -1149,36 +1239,29 @@ static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
void *value)
{
X509_ATTRIBUTE *attr = NULL;
+ int i, n;
if (*sk == NULL) {
if ((*sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
return 0;
- new_attrib:
- if ((attr = X509_ATTRIBUTE_create(nid, atrtype, value)) == NULL)
- return 0;
- if (!sk_X509_ATTRIBUTE_push(*sk, attr)) {
- X509_ATTRIBUTE_free(attr);
- return 0;
- }
- } else {
- int i;
-
- for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) {
- attr = sk_X509_ATTRIBUTE_value(*sk, i);
- if (OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)) == nid) {
- X509_ATTRIBUTE_free(attr);
- attr = X509_ATTRIBUTE_create(nid, atrtype, value);
- if (attr == NULL)
- return 0;
- if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) {
- X509_ATTRIBUTE_free(attr);
- return 0;
- }
- goto end;
- }
- }
- goto new_attrib;
}
+ n = sk_X509_ATTRIBUTE_num(*sk);
+ for (i = 0; i < n; i++) {
+ attr = sk_X509_ATTRIBUTE_value(*sk, i);
+ if (OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)) == nid)
+ goto end;
+ }
+ if (!sk_X509_ATTRIBUTE_push(*sk, NULL))
+ return 0;
+
end:
+ attr = X509_ATTRIBUTE_create(nid, atrtype, value);
+ if (attr == NULL) {
+ if (i == n)
+ sk_X509_ATTRIBUTE_pop(*sk);
+ return 0;
+ }
+ X509_ATTRIBUTE_free(sk_X509_ATTRIBUTE_value(*sk, i));
+ (void) sk_X509_ATTRIBUTE_set(*sk, i, attr);
return 1;
}
diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c
index ec4d9abd587f..bdd620526969 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)
{
@@ -25,6 +28,11 @@ long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
/* NOTE(emilia): does not support detached digested data. */
case PKCS7_OP_SET_DETACHED_SIGNATURE:
if (nid == NID_pkcs7_signed) {
+ if (p7->d.sign == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
+ ret = 0;
+ break;
+ }
ret = p7->detached = (int)larg;
if (ret && PKCS7_type_is_data(p7->d.sign->contents)) {
ASN1_OCTET_STRING *os;
@@ -33,28 +41,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 +104,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 +175,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 +192,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 +209,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 +267,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 +288,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 +307,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 +358,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 +367,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 +400,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 +417,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 +534,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 +573,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 +598,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 +607,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 +631,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 +697,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..d23f7a869f9f 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,19 +31,43 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
{
STACK_OF(X509_ALGOR) *mdalgs;
int ctype_nid = OBJ_obj2nid(p7->type);
- if (ctype_nid == NID_pkcs7_signed)
+ const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7);
+
+ if (ctype_nid == NID_pkcs7_signed) {
+ if (p7->d.sign == NULL)
+ return 0;
mdalgs = p7->d.sign->md_algs;
- else
+ } else {
mdalgs = NULL;
+ }
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..6812829ead30 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,11 +346,9 @@ 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);
- BIO_free(tmpout);
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SMIME_TEXT_ERROR);
goto err;
}
- BIO_free(tmpout);
}
/* Now Verify All Signatures */
@@ -350,7 +358,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;
}
}
@@ -358,6 +366,8 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
ret = 1;
err:
+ if (flags & PKCS7_TEXT)
+ BIO_free(tmpout);
X509_STORE_CTX_free(cert_ctx);
OPENSSL_free(buf);
if (tmpin == indata) {
@@ -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..dc39f4053fe6 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.
+# 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
@@ -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,18 +79,13 @@ 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__
+#ifdef __AARCH64EB__
rev $r0,$r0 // flip bytes
rev $r1,$r1
#endif
@@ -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
@@ -132,7 +132,7 @@ poly1305_blocks:
.Loop:
ldp $t0,$t1,[$inp],#16 // load input
sub $len,$len,#16
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev $t0,$t0
rev $t1,$t1
#endif
@@ -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
@@ -196,13 +197,13 @@ poly1305_emit:
csel $h0,$h0,$d0,eq
csel $h1,$h1,$d1,eq
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
ror $t0,$t0,#32 // flip nonce words
ror $t1,$t1,#32
#endif
adds $h0,$h0,$t0 // accumulate nonce
adc $h1,$h1,$t1
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev $h0,$h0 // flip output bytes
rev $h1,$h1
#endif
@@ -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
@@ -333,7 +335,7 @@ poly1305_blocks_neon:
adcs $h1,$h1,xzr
adc $h2,$h2,xzr
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev $d0,$d0
rev $d1,$d1
#endif
@@ -379,7 +381,7 @@ poly1305_blocks_neon:
ldp $d0,$d1,[$inp],#16 // load input
sub $len,$len,#16
add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev $d0,$d0
rev $d1,$d1
#endif
@@ -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
@@ -464,7 +466,7 @@ poly1305_blocks_neon:
lsl $padbit,$padbit,#24
add x15,$ctx,#48
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev x8,x8
rev x12,x12
rev x9,x9
@@ -500,7 +502,7 @@ poly1305_blocks_neon:
ld1 {$S2,$R3,$S3,$R4},[x15],#64
ld1 {$S4},[x15]
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev x8,x8
rev x12,x12
rev x9,x9
@@ -561,7 +563,7 @@ poly1305_blocks_neon:
umull $ACC1,$IN23_0,${R1}[2]
ldp x9,x13,[$in2],#48
umull $ACC0,$IN23_0,${R0}[2]
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev x8,x8
rev x12,x12
rev x9,x9
@@ -626,7 +628,7 @@ poly1305_blocks_neon:
umlal $ACC4,$IN01_2,${R2}[0]
umlal $ACC1,$IN01_2,${S4}[0]
umlal $ACC2,$IN01_2,${R0}[0]
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev x8,x8
rev x12,x12
rev x9,x9
@@ -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
@@ -906,13 +909,13 @@ poly1305_emit_neon:
csel $h0,$h0,$d0,eq
csel $h1,$h1,$d1,eq
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
ror $t0,$t0,#32 // flip nonce words
ror $t1,$t1,#32
#endif
adds $h0,$h0,$t0 // accumulate nonce
adc $h1,$h1,$t1
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
rev $h0,$h0 // flip output bytes
rev $h1,$h1
#endif
@@ -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..9f9b27cac336 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.
+# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with 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 += 12*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,r11,$sp
+ addi r11,r11,32
+ stvx v24,r10,$sp
+ addi r10,r10,32
+ stvx v25,r11,$sp
+ addi r11,r11,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,r11,$sp
+ addi r11,r11,32
+ stvx v24,r10,$sp
+ addi r10,r10,32
+ stvx v25,r11,$sp
+ addi r11,r11,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,r11,$sp
+ addi r11,r11,32
+ lvx v22,r10,$sp
+ addi r10,r10,32
+ lvx v23,r11,$sp
+ addi r11,r11,32
+ lvx v24,r10,$sp
+ addi r10,r10,32
+ lvx v25,r11,$sp
+ addi r11,r11,32
+ lvx v26,r10,$sp
+ addi r10,r10,32
+ lvx v27,r11,$sp
+ addi r11,r11,32
+ lvx v28,r10,$sp
+ addi r10,r10,32
+ lvx v29,r11,$sp
+ addi r11,r11,32
+ lvx v30,r10,$sp
+ lvx v31,r11,$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..4cddca1c514c 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.
+# 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
@@ -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");
@@ -193,7 +195,7 @@ $code.=<<___ if ($avx>1);
bt \$`5+32`,%r9 # AVX2?
cmovc %rax,%r10
___
-$code.=<<___ if ($avx>3);
+$code.=<<___ if ($avx>3 && !$win64);
mov \$`(1<<31|1<<21|1<<16)`,%rax
shr \$32,%r9
and %rax,%r9
@@ -2722,7 +2724,7 @@ $code.=<<___;
.cfi_endproc
.size poly1305_blocks_avx512,.-poly1305_blocks_avx512
___
-if ($avx>3) {
+if ($avx>3 && !$win64) {
########################################################################
# VPMADD52 version using 2^44 radix.
#
@@ -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..b0a24a7ccb6e
--- /dev/null
+++ b/crypto/property/property.c
@@ -0,0 +1,787 @@
+/*
+ * Copyright 2019-2025 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);
+
+DEFINE_STACK_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,
+ ossl_unused int loadconfig)
+{
+ OSSL_GLOBAL_PROPERTIES *globp;
+
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_AUTOLOAD_CONFIG)
+ 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)) {
+ impl_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);
+}
+
+static void alg_copy(ossl_uintmax_t idx, ALGORITHM *alg, void *arg)
+{
+ STACK_OF(ALGORITHM) *newalg = arg;
+
+ (void)sk_ALGORITHM_push(newalg, alg);
+}
+
+void ossl_method_store_do_all(OSSL_METHOD_STORE *store,
+ void (*fn)(int id, void *method, void *fnarg),
+ void *fnarg)
+{
+ int i, j;
+ int numalgs, numimps;
+ STACK_OF(ALGORITHM) *tmpalgs;
+ ALGORITHM *alg;
+
+ if (store != NULL) {
+
+ if (!ossl_property_read_lock(store))
+ return;
+
+ tmpalgs = sk_ALGORITHM_new_reserve(NULL,
+ ossl_sa_ALGORITHM_num(store->algs));
+ if (tmpalgs == NULL) {
+ ossl_property_unlock(store);
+ return;
+ }
+
+ ossl_sa_ALGORITHM_doall_arg(store->algs, alg_copy, tmpalgs);
+ ossl_property_unlock(store);
+ numalgs = sk_ALGORITHM_num(tmpalgs);
+ for (i = 0; i < numalgs; i++) {
+ alg = sk_ALGORITHM_value(tmpalgs, i);
+ numimps = sk_IMPLEMENTATION_num(alg->impls);
+ for (j = 0; j < numimps; j++)
+ alg_do_one(alg, sk_IMPLEMENTATION_value(alg->impls, j), fn, fnarg);
+ }
+ sk_ALGORITHM_free(tmpalgs);
+ }
+}
+
+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;
+
+ if (nid <= 0 || method == NULL || store == NULL)
+ return 0;
+
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_AUTOLOAD_CONFIG)
+ if (ossl_lib_ctx_is_default(store->ctx)
+ && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
+ return 0;
+#endif
+
+ /* 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;
+ unsigned long orig_down_load = lh_QUERY_get_down_load(alg->cache);
+
+ state->cache = alg->cache;
+ lh_QUERY_set_down_load(alg->cache, 0);
+ lh_QUERY_doall_IMPL_CACHE_FLUSH(state->cache, &impl_cache_flush_cache,
+ state);
+ lh_QUERY_set_down_load(alg->cache, orig_down_load);
+}
+
+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..45c798f1b50b
--- /dev/null
+++ b/crypto/property/property_parse.c
@@ -0,0 +1,763 @@
+/*
+ * Copyright 2019-2024 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 "internal/numbers.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;
+
+ do {
+ if (!ossl_isdigit(*s)) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT,
+ "HERE-->%s", *t);
+ return 0;
+ }
+ /* overflow check */
+ if (v > ((INT64_MAX - (*s - '0')) / 10)) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+ "Property %s overflows", *t);
+ return 0;
+ }
+ 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;
+ int sval;
+
+ do {
+ if (ossl_isdigit(*s)) {
+ sval = *s - '0';
+ } else if (ossl_isxdigit(*s)) {
+ sval = ossl_tolower(*s) - 'a' + 10;
+ } else {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
+ "%s", *t);
+ return 0;
+ }
+
+ if (v > ((INT64_MAX - sval) / 16)) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+ "Property %s overflows", *t);
+ return 0;
+ }
+
+ v <<= 4;
+ v += sval;
+ } 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;
+
+ do {
+ if (*s == '9' || *s == '8' || !ossl_isdigit(*s)) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT,
+ "HERE-->%s", *t);
+ return 0;
+ }
+ if (v > ((INT64_MAX - (*s - '0')) / 8)) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+ "Property %s overflows", *t);
+ return 0;
+ }
+
+ 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, i;
+ char quote = '\0';
+ int quotes;
+
+ len = olen = strlen(str);
+ *needed += len;
+
+ /*
+ * Check to see if we need quotes or not.
+ * Characters that are legal in a PropertyName don't need quoting.
+ * We simply assume all others require quotes.
+ */
+ for (i = 0; i < len; i++)
+ if (!ossl_isalnum(str[i]) && str[i] != '.' && str[i] != '_') {
+ /* Default to single quotes ... */
+ if (quote == '\0')
+ quote = '\'';
+ /* ... but use double quotes if a single is present */
+ if (str[i] == '\'')
+ quote = '"';
+ }
+
+ quotes = quote != '\0';
+ if (*remain == 0) {
+ *needed += 2 * quotes;
+ return;
+ }
+
+ if (quotes)
+ put_char(quote, buf, remain, needed);
+
+ if (*remain < len + 1 + quotes)
+ len = *remain - 1;
+
+ if (len > 0) {
+ memcpy(*buf, str, len);
+ *buf += len;
+ *remain -= len;
+ }
+
+ if (quotes)
+ put_char(quote, buf, remain, needed);
+
+ 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..b42e8412bec0
--- /dev/null
+++ b/crypto/provider_conf.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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;
+}
+
+/*
+ * Parse the provider params section
+ * Returns:
+ * 1 for success
+ * 0 for non-fatal errors
+ * < 0 for fatal errors
+ */
+static int provider_conf_params_internal(OSSL_PROVIDER *prov,
+ OSSL_PROVIDER_INFO *provinfo,
+ const char *name, const char *value,
+ const CONF *cnf,
+ STACK_OF(OPENSSL_CSTRING) *visited)
+{
+ STACK_OF(CONF_VALUE) *sect;
+ int ok = 1;
+ int rc = 0;
+
+ 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);
+
+ /*
+ * Check to see if the provided section value has already
+ * been visited. If it has, then we have a recursive lookup
+ * in the configuration which isn't valid. As such we should error
+ * out
+ */
+ for (i = 0; i < sk_OPENSSL_CSTRING_num(visited); i++) {
+ if (sk_OPENSSL_CSTRING_value(visited, i) == value) {
+ ERR_raise(ERR_LIB_CONF, CONF_R_RECURSIVE_SECTION_REFERENCE);
+ return -1;
+ }
+ }
+
+ /*
+ * We've not visited this node yet, so record it on the stack
+ */
+ if (!sk_OPENSSL_CSTRING_push(visited, value))
+ return -1;
+
+ 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)) {
+ sk_OPENSSL_CSTRING_pop(visited);
+ return -1;
+ }
+ buffer[buffer_len] = '\0';
+ OPENSSL_strlcat(buffer, sectconf->name, sizeof(buffer));
+ rc = provider_conf_params_internal(prov, provinfo, buffer,
+ sectconf->value, cnf, visited);
+ if (rc < 0) {
+ sk_OPENSSL_CSTRING_pop(visited);
+ return rc;
+ }
+ }
+ sk_OPENSSL_CSTRING_pop(visited);
+
+ 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;
+}
+
+/*
+ * recursively parse the provider configuration section
+ * of the config file.
+ * Returns
+ * 1 on success
+ * 0 on non-fatal error
+ * < 0 on fatal errors
+ */
+static int provider_conf_params(OSSL_PROVIDER *prov,
+ OSSL_PROVIDER_INFO *provinfo,
+ const char *name, const char *value,
+ const CONF *cnf)
+{
+ int rc;
+ STACK_OF(OPENSSL_CSTRING) *visited = sk_OPENSSL_CSTRING_new_null();
+
+ if (visited == NULL)
+ return -1;
+
+ rc = provider_conf_params_internal(prov, provinfo, name,
+ value, cnf, visited);
+
+ sk_OPENSSL_CSTRING_free(visited);
+
+ return rc;
+}
+
+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;
+ int added = 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 > 0) {
+ 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 <= 0)
+ 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 >= 1 && (entry.path != NULL || entry.parameters != NULL)) {
+ ok = ossl_provider_info_add_to_store(libctx, &entry);
+ added = ok;
+ }
+ if (added == 0)
+ ossl_provider_info_clear(&entry);
+ }
+
+ /*
+ * Provider activation returns a tristate:
+ * 1 for successful activation
+ * 0 for non-fatal activation failure
+ * < 0 for fatal activation failure
+ * We return success (1) for activation, (1) for non-fatal activation
+ * failure, and (0) for fatal activation failure
+ */
+ return ok >= 0;
+}
+
+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..cb4233eb52fd
--- /dev/null
+++ b/crypto/provider_core.c
@@ -0,0 +1,2180 @@
+/*
+ * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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,
+ ossl_unused 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;
+
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_AUTOLOAD_CONFIG)
+ /*
+ * 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 */
+ prov = provider_new(name, template.init, template.parameters);
+
+ if (prov == NULL)
+ return NULL;
+
+ if (!ossl_provider_set_module_path(prov, template.path)) {
+ ossl_provider_free(prov);
+ 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;
+
+ if (provider_dispatch != NULL) {
+ 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;
+
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_AUTOLOAD_CONFIG)
+ /*
+ * 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..5fde214448f3 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.
+ * 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 <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,731 @@ void RAND_keep_random_devices_open(int keep)
*/
int RAND_poll(void)
{
- int ret = 0;
-
- RAND_POOL *pool = NULL;
+ static const char salt[] = "polling";
+# 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);
+ return ret;
}
+# endif
-err:
- rand_pool_free(pool);
- return ret;
+ RAND_seed(salt, sizeof(salt));
+ return 1;
}
-/*
- * 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);
+}
- pool->attached = 1;
+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->min_len = pool->max_len = pool->alloc_len = pool->len;
- pool->entropy = entropy;
+ if (meth != NULL && meth->add != NULL) {
+ meth->add(buf, num, randomness);
+ return;
+ }
+# endif
+ drbg = RAND_get0_primary(NULL);
+ if (drbg != NULL && num > 0)
+# ifdef OPENSSL_RAND_SEED_NONE
+ /* Without an entropy source, we have to rely on the user */
+ EVP_RAND_reseed(drbg, 0, buf, num, NULL, 0);
+# else
+ /* With an entropy source, we downgrade this to additional input */
+ EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
+# endif
+}
+
+# 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;
- }
+ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX,
+ &rand_drbg_ossl_ctx_method);
+}
- bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_factor);
+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 (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;
- }
+ if (dgbl == NULL)
+ return;
- 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;
+ rand = CRYPTO_THREAD_get_local(&dgbl->public);
+ CRYPTO_THREAD_set_local(&dgbl->public, NULL);
+ EVP_RAND_CTX_free(rand);
- /*
- * 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;
- }
-
- 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..b4854a4c4eab 100644
--- a/crypto/rand/randfile.c
+++ b/crypto/rand/randfile.c
@@ -1,12 +1,22 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 <errno.h>
@@ -16,7 +26,6 @@
#include <openssl/crypto.h>
#include <openssl/rand.h>
-#include <openssl/rand_drbg.h>
#include <openssl/buffer.h>
#ifdef OPENSSL_SYS_VMS
@@ -95,15 +104,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 +172,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 +188,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
@@ -201,8 +209,16 @@ int RAND_write_file(const char *file)
* should be restrictive from the start
*/
int fd = open(file, O_WRONLY | O_CREAT | O_BINARY, 0600);
- if (fd != -1)
+
+ if (fd != -1) {
out = fdopen(fd, "wb");
+ if (out == NULL) {
+ close(fd);
+ ERR_raise_data(ERR_LIB_RAND, RAND_R_CANNOT_OPEN_FILE,
+ "Filename=%s", file);
+ return -1;
+ }
+ }
}
#endif
@@ -230,8 +246,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..c9c81f87dabf 100644
--- a/crypto/rc4/build.info
+++ b/crypto/rc4/build.info
@@ -1,20 +1,41 @@
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{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]
+# Implementations are now spread across several libraries, so the defines
+# need to be applied to all affected libraries and modules.
+DEFINE[../../libcrypto]=$RC4DEF
+DEFINE[../../providers/liblegacy.a]=$RC4DEF
+
+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..07734077e322 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-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 <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;
@@ -82,17 +60,20 @@ static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
if (!rsa_param_encode(pkey, &str, &strtype))
return 0;
penclen = i2d_RSAPublicKey(pkey->pkey.rsa, &penc);
- if (penclen <= 0)
+ if (penclen <= 0) {
+ ASN1_STRING_free(str);
return 0;
+ }
if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
strtype, str, penc, penclen))
return 1;
OPENSSL_free(penc);
+ ASN1_STRING_free(str);
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 +82,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 +131,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 +154,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 +172,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_param_decode(rsa, alg)) {
- RSA_free(rsa);
- return 0;
+ if (rsa != NULL) {
+ ret = 1;
+ EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
}
- EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
- return 1;
+ return ret;
}
static int int_rsa_size(const EVP_PKEY *pkey)
@@ -221,14 +202,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 +253,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 +284,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 +398,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 +419,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 +440,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 +458,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 +487,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 +501,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 +520,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 +530,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 +549,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 +571,131 @@ 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)
- return 0;
- /* Duplicate parameters if we have to */
- if (alg2) {
- ASN1_STRING *os2 = ASN1_STRING_dup(os1);
- if (!os2) {
- ASN1_STRING_free(os1);
+ unsigned char aid[128];
+ size_t aid_len = 0;
+ OSSL_PARAM params[2];
+
+ if (evp_pkey_ctx_is_legacy(pkctx)) {
+ /* No provider -> we cannot query it for algorithm ID. */
+ ASN1_STRING *os1 = NULL;
+
+ os1 = ossl_rsa_ctx_to_pss_string(pkctx);
+ if (os1 == NULL)
return 0;
+ /* Duplicate parameters if we have to */
+ if (alg2 != NULL) {
+ ASN1_STRING *os2 = ASN1_STRING_dup(os1);
+
+ if (os2 == NULL) {
+ ASN1_STRING_free(os1);
+ return 0;
+ }
+ if (!X509_ALGOR_set0(alg2, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
+ V_ASN1_SEQUENCE, os2)) {
+ ASN1_STRING_free(os1);
+ ASN1_STRING_free(os2);
+ return 0;
+ }
+ }
+ if (!X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
+ V_ASN1_SEQUENCE, os1)) {
+ ASN1_STRING_free(os1);
+ return 0;
}
- X509_ALGOR_set0(alg2, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
- V_ASN1_SEQUENCE, os2);
+ return 3;
+ }
+
+ 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 (alg1 != NULL) {
+ const unsigned char *pp = aid;
+
+ if (d2i_X509_ALGOR(&alg1, &pp, aid_len) == NULL)
+ return 0;
+ }
+ if (alg2 != NULL) {
+ const unsigned char *pp = aid;
+
+ if (d2i_X509_ALGOR(&alg2, &pp, aid_len) == NULL)
+ return 0;
}
- X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
- V_ASN1_SEQUENCE, os1);
+
return 3;
}
return 2;
@@ -865,26 +709,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 +755,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;
+ return RSA_check_key_ex(pkey->pkey.rsa, 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;
+static size_t rsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
+{
+ return pkey->pkey.rsa->dirty_cnt;
}
-static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
+/*
+ * 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)
{
- 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;
+ RSA *rsa = from->pkey.rsa;
+ OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
+ OSSL_PARAM *params = NULL;
+ int selection = 0;
+ int rv = 0;
- pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
- if (pkctx == NULL)
+ if (tmpl == 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);
-
- if (oaep == NULL) {
- RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS);
+ /* 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 (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
- RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE);
+ 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 (!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)
+ if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
goto err;
- if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0)
- 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);
}
-const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
+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 ossl_rsa_asn1_meths[2] = {
{
EVP_PKEY_RSA,
EVP_PKEY_RSA,
@@ -1087,7 +973,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 +990,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 +1019,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..f9d1cb361d77
--- /dev/null
+++ b/crypto/rsa/rsa_backend.c
@@ -0,0 +1,583 @@
+/*
+ * 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
+ */
+
+/*
+ * 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) {
+
+ 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..c2549188f556 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-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 <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)? */
@@ -122,13 +124,17 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
ret = -1;
goto err;
}
+ if (!BN_div(m, NULL, l, m, ctx)) { /* remainder is 0 */
+ ret = -1;
+ goto err;
+ }
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
if (!BN_sub(k, pinfo->r, BN_value_one())) {
ret = -1;
goto err;
}
- if (!BN_mul(l, l, k, ctx)) {
+ if (!BN_mul(l, m, k, ctx)) {
ret = -1;
goto err;
}
@@ -136,19 +142,19 @@ int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
ret = -1;
goto err;
}
+ if (!BN_div(m, NULL, l, m, ctx)) { /* remainder is 0 */
+ ret = -1;
+ goto err;
+ }
}
- if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */
- ret = -1;
- goto err;
- }
- if (!BN_mod_mul(i, key->d, key->e, k, ctx)) {
+ if (!BN_mod_mul(i, key->d, key->e, m, ctx)) {
ret = -1;
goto err;
}
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 +169,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 +183,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 +193,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 +210,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 +219,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 +232,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..c9c661b1ede9 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-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>
+/*
+ * 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,569 @@ 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)
+ return 0;
+
+ if (!RSA_set0_factors(r, sk_BIGNUM_value(primes, 0),
+ sk_BIGNUM_value(primes, 1)))
+ return 0;
+
+ if (pnum == sk_BIGNUM_num(exps)
+ && pnum == sk_BIGNUM_num(coeffs) + 1) {
+
+ if (!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)
+{
+ /* If key type not RSA return error */
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA"))
+ return -1;
+
+ 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)
+{
+ /* If key type not RSA return error */
+ if (!EVP_PKEY_CTX_is_a(ctx, "RSA"))
+ return -1;
+
+ 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;
+ const char *empty = "";
+ /*
+ * Needed as we swap label with empty if it is NULL, and label is
+ * freed at the end of this function.
+ */
+ void *plabel = label;
+ 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;
+
+ /* Accept NULL for backward compatibility */
+ if (label == NULL && llen == 0)
+ plabel = (void *)empty;
+
+ /* 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 *)plabel, (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..ffe24edcb6ee 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,14 +172,21 @@ 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)
+ if (tlen <= 0 || flen <= 0 || mdlen <= 0)
return -1;
/*
* |num| is the length of the modulus; |flen| is the length of the
@@ -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..0fc642e777fd 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);
@@ -226,6 +234,7 @@ static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
* will only read the modulus from BN_BLINDING. In both cases it's safe
* to access the blinding without a lock.
*/
+ BN_set_flags(f, BN_FLG_CONSTTIME);
return BN_BLINDING_invert_ex(f, unblind, b, ctx);
}
@@ -246,7 +255,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 +263,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 +277,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 +289,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 +301,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 +325,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 +387,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 +395,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 +404,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 +413,26 @@ 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_CACHE_PUBLIC)
+ if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
+ rsa->n, ctx))
+ 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,22 +450,15 @@ 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;
}
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
- rsa->n, ctx)) {
- BN_free(d);
- goto err;
- }
if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx,
rsa->_method_mod_n)) {
BN_free(d);
@@ -465,20 +468,13 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
BN_free(d);
}
- if (blinding) {
- /*
- * ossl_bn_rsa_do_unblind() combines blinding inversion and
- * 0-padded BN BE serialization
- */
- j = ossl_bn_rsa_do_unblind(ret, blinding, unblind, rsa->n, ctx,
- buf, num);
- if (j == 0)
- goto err;
- } else {
- j = BN_bn2binpad(ret, buf, num);
- if (j < 0)
+ if (blinding)
+ if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
goto err;
- }
+
+ j = BN_bn2binpad(ret, buf, num);
+ if (j < 0)
+ goto err;
switch (padding) {
case RSA_PKCS1_PADDING:
@@ -487,18 +483,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 +517,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 +542,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 +551,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 +559,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 +577,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 +591,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 +606,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 +651,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 +660,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 +689,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 +780,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 +820,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 +864,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 +907,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 +983,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..0bf5ac098ac0 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-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/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,9 +581,13 @@ 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;
}
+ if (p2 == NULL) {
+ ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
*(unsigned char **)p2 = rctx->oaep_label;
return rctx->oaep_labellen;
@@ -576,8 +608,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 +621,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 +629,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 +640,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 +672,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 +736,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 +783,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 +818,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 +830,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 +839,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 +870,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 +893,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..df81397f5478
--- /dev/null
+++ b/crypto/rsa/rsa_sp800_56b_check.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2018-2024 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);
+ if (nbits > OPENSSL_RSA_MAX_MODULUS_BITS) {
+ ERR_raise(ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE);
+ return 0;
+ }
+
+#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;
+ }
+
+ /* Highest number of MR rounds from FIPS 186-5 Section B.3 Table B.1 */
+ ret = ossl_bn_miller_rabin_is_prime(rsa->n, 5, 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..f773d1e149de
--- /dev/null
+++ b/crypto/rsa/rsa_sp800_56b_gen.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright 2018-2023 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;
+ BIGNUM *tmp;
+
+#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;
+
+ /* p>q check and skipping in case of acvp test */
+ if (info == NULL && BN_cmp(rsa->p, rsa->q) < 0) {
+ tmp = rsa->p;
+ rsa->p = rsa->q;
+ rsa->q = tmp;
+ }
+
+ /* (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..864066533445 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.
+# Copyright 2017-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
@@ -432,6 +432,7 @@ $code.=<<___;
ret
.size SHA3_squeeze,.-SHA3_squeeze
+.section .rodata
.align 64
rhotates_left:
.quad 3, 18, 36, 41 # [2][0] [4][0] [1][0] [3][0]
@@ -476,7 +477,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..efc32545c356 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.
+# Copyright 2017-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
@@ -486,6 +486,7 @@ SHA3_squeeze:
ret
.size SHA3_squeeze,.-SHA3_squeeze
+.section .rodata
.align 64
theta_perm:
.quad 0, 1, 2, 3, 4, 5, 6, 7 # [not used]
@@ -545,7 +546,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..f941556b42a8 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.
+# Copyright 2017-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
@@ -349,6 +349,7 @@ $code.=<<___;
ret
.size SHA3_squeeze,.-SHA3_squeeze
+.section .rodata
.align 64
rhotates_left:
.quad 3, 18, 36, 41 # [2][0] [4][0] [1][0] [3][0]
@@ -386,7 +387,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-alpha.pl b/crypto/sha/asm/sha1-alpha.pl
new file mode 100644
index 000000000000..0ffc090602e1
--- /dev/null
+++ b/crypto/sha/asm/sha1-alpha.pl
@@ -0,0 +1,329 @@
+#! /usr/bin/env perl
+# Copyright 2009-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/.
+# ====================================================================
+
+# SHA1 block procedure for Alpha.
+
+# On 21264 performance is 33% better than code generated by vendor
+# compiler, and 75% better than GCC [3.4], and in absolute terms is
+# 8.7 cycles per processed byte. Implementation features vectorized
+# byte swap, but not Xupdate.
+
+@X=( "\$0", "\$1", "\$2", "\$3", "\$4", "\$5", "\$6", "\$7",
+ "\$8", "\$9", "\$10", "\$11", "\$12", "\$13", "\$14", "\$15");
+$ctx="a0"; # $16
+$inp="a1";
+$num="a2";
+$A="a3";
+$B="a4"; # 20
+$C="a5";
+$D="t8";
+$E="t9"; @V=($A,$B,$C,$D,$E);
+$t0="t10"; # 24
+$t1="t11";
+$t2="ra";
+$t3="t12";
+$K="AT"; # 28
+
+sub BODY_00_19 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=$i+1;
+$code.=<<___ if ($i==0);
+ ldq_u @X[0],0+0($inp)
+ ldq_u @X[1],0+7($inp)
+___
+$code.=<<___ if (!($i&1) && $i<14);
+ ldq_u @X[$i+2],($i+2)*4+0($inp)
+ ldq_u @X[$i+3],($i+2)*4+7($inp)
+___
+$code.=<<___ if (!($i&1) && $i<15);
+ extql @X[$i],$inp,@X[$i]
+ extqh @X[$i+1],$inp,@X[$i+1]
+
+ or @X[$i+1],@X[$i],@X[$i] # pair of 32-bit values are fetched
+
+ srl @X[$i],24,$t0 # vectorized byte swap
+ srl @X[$i],8,$t2
+
+ sll @X[$i],8,$t3
+ sll @X[$i],24,@X[$i]
+ zapnot $t0,0x11,$t0
+ zapnot $t2,0x22,$t2
+
+ zapnot @X[$i],0x88,@X[$i]
+ or $t0,$t2,$t0
+ zapnot $t3,0x44,$t3
+ sll $a,5,$t1
+
+ or @X[$i],$t0,@X[$i]
+ addl $K,$e,$e
+ and $b,$c,$t2
+ zapnot $a,0xf,$a
+
+ or @X[$i],$t3,@X[$i]
+ srl $a,27,$t0
+ bic $d,$b,$t3
+ sll $b,30,$b
+
+ extll @X[$i],4,@X[$i+1] # extract upper half
+ or $t2,$t3,$t2
+ addl @X[$i],$e,$e
+
+ addl $t1,$e,$e
+ srl $b,32,$t3
+ zapnot @X[$i],0xf,@X[$i]
+
+ addl $t0,$e,$e
+ addl $t2,$e,$e
+ or $t3,$b,$b
+___
+$code.=<<___ if (($i&1) && $i<15);
+ sll $a,5,$t1
+ addl $K,$e,$e
+ and $b,$c,$t2
+ zapnot $a,0xf,$a
+
+ srl $a,27,$t0
+ addl @X[$i%16],$e,$e
+ bic $d,$b,$t3
+ sll $b,30,$b
+
+ or $t2,$t3,$t2
+ addl $t1,$e,$e
+ srl $b,32,$t3
+ zapnot @X[$i],0xf,@X[$i]
+
+ addl $t0,$e,$e
+ addl $t2,$e,$e
+ or $t3,$b,$b
+___
+$code.=<<___ if ($i>=15); # with forward Xupdate
+ sll $a,5,$t1
+ addl $K,$e,$e
+ and $b,$c,$t2
+ xor @X[($j+2)%16],@X[$j%16],@X[$j%16]
+
+ zapnot $a,0xf,$a
+ addl @X[$i%16],$e,$e
+ bic $d,$b,$t3
+ xor @X[($j+8)%16],@X[$j%16],@X[$j%16]
+
+ srl $a,27,$t0
+ addl $t1,$e,$e
+ or $t2,$t3,$t2
+ xor @X[($j+13)%16],@X[$j%16],@X[$j%16]
+
+ sll $b,30,$b
+ addl $t0,$e,$e
+ srl @X[$j%16],31,$t1
+
+ addl $t2,$e,$e
+ srl $b,32,$t3
+ addl @X[$j%16],@X[$j%16],@X[$j%16]
+
+ or $t3,$b,$b
+ zapnot @X[$i%16],0xf,@X[$i%16]
+ or $t1,@X[$j%16],@X[$j%16]
+___
+}
+
+sub BODY_20_39 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=$i+1;
+$code.=<<___ if ($i<79); # with forward Xupdate
+ sll $a,5,$t1
+ addl $K,$e,$e
+ zapnot $a,0xf,$a
+ xor @X[($j+2)%16],@X[$j%16],@X[$j%16]
+
+ sll $b,30,$t3
+ addl $t1,$e,$e
+ xor $b,$c,$t2
+ xor @X[($j+8)%16],@X[$j%16],@X[$j%16]
+
+ srl $b,2,$b
+ addl @X[$i%16],$e,$e
+ xor $d,$t2,$t2
+ xor @X[($j+13)%16],@X[$j%16],@X[$j%16]
+
+ srl @X[$j%16],31,$t1
+ addl $t2,$e,$e
+ srl $a,27,$t0
+ addl @X[$j%16],@X[$j%16],@X[$j%16]
+
+ or $t3,$b,$b
+ addl $t0,$e,$e
+ or $t1,@X[$j%16],@X[$j%16]
+___
+$code.=<<___ if ($i<77);
+ zapnot @X[$i%16],0xf,@X[$i%16]
+___
+$code.=<<___ if ($i==79); # with context fetch
+ sll $a,5,$t1
+ addl $K,$e,$e
+ zapnot $a,0xf,$a
+ ldl @X[0],0($ctx)
+
+ sll $b,30,$t3
+ addl $t1,$e,$e
+ xor $b,$c,$t2
+ ldl @X[1],4($ctx)
+
+ srl $b,2,$b
+ addl @X[$i%16],$e,$e
+ xor $d,$t2,$t2
+ ldl @X[2],8($ctx)
+
+ srl $a,27,$t0
+ addl $t2,$e,$e
+ ldl @X[3],12($ctx)
+
+ or $t3,$b,$b
+ addl $t0,$e,$e
+ ldl @X[4],16($ctx)
+___
+}
+
+sub BODY_40_59 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=$i+1;
+$code.=<<___; # with forward Xupdate
+ sll $a,5,$t1
+ addl $K,$e,$e
+ zapnot $a,0xf,$a
+ xor @X[($j+2)%16],@X[$j%16],@X[$j%16]
+
+ srl $a,27,$t0
+ and $b,$c,$t2
+ and $b,$d,$t3
+ xor @X[($j+8)%16],@X[$j%16],@X[$j%16]
+
+ sll $b,30,$b
+ addl $t1,$e,$e
+ xor @X[($j+13)%16],@X[$j%16],@X[$j%16]
+
+ srl @X[$j%16],31,$t1
+ addl $t0,$e,$e
+ or $t2,$t3,$t2
+ and $c,$d,$t3
+
+ or $t2,$t3,$t2
+ srl $b,32,$t3
+ addl @X[$i%16],$e,$e
+ addl @X[$j%16],@X[$j%16],@X[$j%16]
+
+ or $t3,$b,$b
+ addl $t2,$e,$e
+ or $t1,@X[$j%16],@X[$j%16]
+ zapnot @X[$i%16],0xf,@X[$i%16]
+___
+}
+
+$code=<<___;
+#ifdef __linux__
+#include <asm/regdef.h>
+#else
+#include <asm.h>
+#include <regdef.h>
+#endif
+
+.text
+
+.set noat
+.set noreorder
+.globl sha1_block_data_order
+.align 5
+.ent sha1_block_data_order
+sha1_block_data_order:
+ lda sp,-64(sp)
+ stq ra,0(sp)
+ stq s0,8(sp)
+ stq s1,16(sp)
+ stq s2,24(sp)
+ stq s3,32(sp)
+ stq s4,40(sp)
+ stq s5,48(sp)
+ stq fp,56(sp)
+ .mask 0x0400fe00,-64
+ .frame sp,64,ra
+ .prologue 0
+
+ ldl $A,0($ctx)
+ ldl $B,4($ctx)
+ sll $num,6,$num
+ ldl $C,8($ctx)
+ ldl $D,12($ctx)
+ ldl $E,16($ctx)
+ addq $inp,$num,$num
+
+.Lloop:
+ .set noreorder
+ ldah $K,23170(zero)
+ zapnot $B,0xf,$B
+ lda $K,31129($K) # K_00_19
+___
+for ($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); }
+
+$code.=<<___;
+ ldah $K,28378(zero)
+ lda $K,-5215($K) # K_20_39
+___
+for (;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+
+$code.=<<___;
+ ldah $K,-28900(zero)
+ lda $K,-17188($K) # K_40_59
+___
+for (;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
+
+$code.=<<___;
+ ldah $K,-13725(zero)
+ lda $K,-15914($K) # K_60_79
+___
+for (;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+
+$code.=<<___;
+ addl @X[0],$A,$A
+ addl @X[1],$B,$B
+ addl @X[2],$C,$C
+ addl @X[3],$D,$D
+ addl @X[4],$E,$E
+ stl $A,0($ctx)
+ stl $B,4($ctx)
+ addq $inp,64,$inp
+ stl $C,8($ctx)
+ stl $D,12($ctx)
+ stl $E,16($ctx)
+ cmpult $inp,$num,$t1
+ bne $t1,.Lloop
+
+ .set noreorder
+ ldq ra,0(sp)
+ ldq s0,8(sp)
+ ldq s1,16(sp)
+ ldq s2,24(sp)
+ ldq s3,32(sp)
+ ldq s4,40(sp)
+ ldq s5,48(sp)
+ ldq fp,56(sp)
+ lda sp,64(sp)
+ ret (ra)
+.end sha1_block_data_order
+.ascii "SHA1 block transform for Alpha, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+___
+$output=pop and open STDOUT,">$output";
+print $code;
+close STDOUT or die "error closing STDOUT: $!";
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..186ec13cc82a 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..ff8171e39280 100644
--- a/crypto/sm2/sm2_crypt.c
+++ b/crypto/sm2/sm2_crypt.c
@@ -1,17 +1,23 @@
/*
- * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2024 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
*/
+/*
+ * 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,27 @@ 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)
+static int is_all_zeros(const unsigned char *msg, size_t msglen)
+{
+ unsigned char re = 0;
+ size_t i;
+
+ for (i = 0; i < msglen; i++) {
+ re |= msg[i];
+ }
+
+ return re == 0 ? 1 : 0;
+}
+
+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 +97,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 +117,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 +141,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 +177,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 +185,21 @@ 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);
+ msg_mask = OPENSSL_zalloc(msg_len);
+ if (msg_mask == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
+again:
+ if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
goto done;
}
@@ -178,38 +207,42 @@ 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);
- 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;
}
+ if (is_all_zeros(msg_mask, msg_len)) {
+ memset(x2y2, 0, 2 * field_size);
+ goto again;
+ }
+
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 +252,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 +272,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 +285,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 +301,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 +318,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 +331,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 +346,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 +355,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 +370,20 @@ 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;
+ }
+
+ if (is_all_zeros(msg_mask, msg_len)) {
+ ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
goto done;
}
@@ -351,7 +392,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 +401,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..2097cd2fca86 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-2024 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,14 +21,15 @@
#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);
+ const EC_POINT *pubkey = EC_KEY_get0_public_key(key);
BN_CTX *ctx = NULL;
EVP_MD_CTX *hash = NULL;
BIGNUM *p = NULL;
@@ -41,10 +44,16 @@ int sm2_compute_z_digest(uint8_t *out,
uint16_t entl = 0;
uint8_t e_byte = 0;
+ /* SM2 Signatures require a public key, check for it */
+ if (pubkey == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER);
+ goto done;
+ }
+
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 +66,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 +79,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 +87,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;
}
@@ -116,14 +125,14 @@ int sm2_compute_z_digest(uint8_t *out,
|| BN_bn2binpad(yG, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| !EC_POINT_get_affine_coordinates(group,
- EC_KEY_get0_public_key(key),
+ pubkey,
xA, yA, ctx)
|| BN_bn2binpad(xA, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| 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 +152,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 +215,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 +230,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 +242,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 +265,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 +274,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 +282,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,19 +328,24 @@ 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();
- pt = EC_POINT_new(group);
- if (ctx == NULL || pt == NULL) {
- SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE);
+ ctx = BN_CTX_new_ex(libctx);
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
-
BN_CTX_start(ctx);
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;
+ }
+
+ pt = EC_POINT_new(group);
+ if (pt == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -327,28 +365,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 +399,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 +421,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,25 +444,35 @@ 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;
int sigleni;
int ret = -1;
+ if (sig == NULL) {
+ ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER);
+ goto done;
+ }
+
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 +485,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 +498,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..4b842dfd9129 100644
--- a/crypto/srp/srp_vfy.c
+++ b/crypto/srp/srp_vfy.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2023 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,20 @@ 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);
+ vinfo->id = NULL;
+ vinfo->info = NULL;
if (id != NULL && NULL == (vinfo->id = OPENSSL_strdup(id)))
return 0;
return (info == NULL || NULL != (vinfo->info = OPENSSL_strdup(info)));
@@ -243,8 +250,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 +269,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;
}
@@ -276,6 +285,7 @@ SRP_VBASE *SRP_VBASE_new(char *seed_key)
return NULL;
if ((vb->users_pwd = sk_SRP_user_pwd_new_null()) == NULL
|| (vb->gN_cache = sk_SRP_gN_cache_new_null()) == NULL) {
+ sk_SRP_user_pwd_free(vb->users_pwd);
OPENSSL_free(vb);
return NULL;
}
@@ -340,12 +350,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 +385,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 +456,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 +524,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 +554,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 +573,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 +607,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 +639,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 +648,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 +660,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 +698,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 +713,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 +731,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 +741,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 +766,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..bc12d8dd13a2 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-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 "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;
+ ctx->error_flag = 0;
+
+ if (!ctx->fetched_loader->p_load(ctx->loader_ctx,
+ ossl_store_handle_load_result,
+ &load_data,
+ ossl_pw_passphrase_callback_dec,
+ &ctx->pwdata)) {
+ 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..bbc8f6fef265
--- /dev/null
+++ b/crypto/store/store_result.c
@@ -0,0 +1,650 @@
+/*
+ * 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
+ */
+
+#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_mac_present(p12)
+ || PKCS12_verify_mac(p12, NULL, 0)) {
+ pass = NULL;
+ } else if (PKCS12_verify_mac(p12, "", 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..303f481bef12 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,17 @@ 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);
+# 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 +89,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 +125,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 +198,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 +222,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_ACQ_REL) && !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/threads_win.c b/crypto/threads_win.c
new file mode 100644
index 000000000000..43f36ee6a333
--- /dev/null
+++ b/crypto/threads_win.c
@@ -0,0 +1,264 @@
+/*
+ * 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#if defined(_WIN32)
+# include <windows.h>
+# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+# define USE_RWLOCK
+# endif
+#endif
+
+/*
+ * VC++ 2008 or earlier x86 compilers do not have an inline implementation
+ * of InterlockedOr64 for 32bit and will fail to run on Windows XP 32bit.
+ * https://docs.microsoft.com/en-us/cpp/intrinsics/interlockedor-intrinsic-functions#requirements
+ * To work around this problem, we implement a manual locking mechanism for
+ * only VC++ 2008 or earlier x86 compilers.
+ */
+
+#if (defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER <= 1600)
+# define NO_INTERLOCKEDOR64
+#endif
+
+#include <openssl/crypto.h>
+
+#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS)
+
+# ifdef USE_RWLOCK
+typedef struct {
+ SRWLOCK lock;
+ int exclusive;
+} CRYPTO_win_rwlock;
+# endif
+
+CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
+{
+ CRYPTO_RWLOCK *lock;
+# ifdef USE_RWLOCK
+ CRYPTO_win_rwlock *rwlock;
+
+ if ((lock = OPENSSL_zalloc(sizeof(CRYPTO_win_rwlock))) == NULL)
+ return NULL;
+ rwlock = lock;
+ InitializeSRWLock(&rwlock->lock);
+# else
+
+ if ((lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION))) == NULL) {
+ /* Don't set error, to avoid recursion blowup. */
+ return NULL;
+ }
+
+# if !defined(_WIN32_WCE)
+ /* 0x400 is the spin count value suggested in the documentation */
+ if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) {
+ OPENSSL_free(lock);
+ return NULL;
+ }
+# else
+ InitializeCriticalSection(lock);
+# endif
+# endif
+
+ return lock;
+}
+
+__owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
+{
+# ifdef USE_RWLOCK
+ CRYPTO_win_rwlock *rwlock = lock;
+
+ AcquireSRWLockShared(&rwlock->lock);
+# else
+ EnterCriticalSection(lock);
+# endif
+ return 1;
+}
+
+__owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
+{
+# ifdef USE_RWLOCK
+ CRYPTO_win_rwlock *rwlock = lock;
+
+ AcquireSRWLockExclusive(&rwlock->lock);
+ rwlock->exclusive = 1;
+# else
+ EnterCriticalSection(lock);
+# endif
+ return 1;
+}
+
+int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
+{
+# ifdef USE_RWLOCK
+ CRYPTO_win_rwlock *rwlock = lock;
+
+ if (rwlock->exclusive) {
+ rwlock->exclusive = 0;
+ ReleaseSRWLockExclusive(&rwlock->lock);
+ } else {
+ ReleaseSRWLockShared(&rwlock->lock);
+ }
+# else
+ LeaveCriticalSection(lock);
+# endif
+ return 1;
+}
+
+void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
+{
+ if (lock == NULL)
+ return;
+
+# ifndef USE_RWLOCK
+ DeleteCriticalSection(lock);
+# endif
+ OPENSSL_free(lock);
+
+ return;
+}
+
+# define ONCE_UNINITED 0
+# define ONCE_ININIT 1
+# define ONCE_DONE 2
+
+/*
+ * We don't use InitOnceExecuteOnce because that isn't available in WinXP which
+ * we still have to support.
+ */
+int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
+{
+ LONG volatile *lock = (LONG *)once;
+ LONG result;
+
+ if (*lock == ONCE_DONE)
+ return 1;
+
+ do {
+ result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED);
+ if (result == ONCE_UNINITED) {
+ init();
+ *lock = ONCE_DONE;
+ return 1;
+ }
+ } while (result == ONCE_ININIT);
+
+ return (*lock == ONCE_DONE);
+}
+
+int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
+{
+ *key = TlsAlloc();
+ if (*key == TLS_OUT_OF_INDEXES)
+ return 0;
+
+ return 1;
+}
+
+void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key)
+{
+ DWORD last_error;
+ void *ret;
+
+ /*
+ * TlsGetValue clears the last error even on success, so that callers may
+ * distinguish it successfully returning NULL or failing. It is documented
+ * to never fail if the argument is a valid index from TlsAlloc, so we do
+ * not need to handle this.
+ *
+ * However, this error-mangling behavior interferes with the caller's use of
+ * GetLastError. In particular SSL_get_error queries the error queue to
+ * determine whether the caller should look at the OS's errors. To avoid
+ * destroying state, save and restore the Windows error.
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms686812(v=vs.85).aspx
+ */
+ last_error = GetLastError();
+ ret = TlsGetValue(*key);
+ SetLastError(last_error);
+ return ret;
+}
+
+int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val)
+{
+ if (TlsSetValue(*key, val) == 0)
+ return 0;
+
+ return 1;
+}
+
+int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key)
+{
+ if (TlsFree(*key) == 0)
+ return 0;
+
+ return 1;
+}
+
+CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void)
+{
+ return GetCurrentThreadId();
+}
+
+int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b)
+{
+ return (a == b);
+}
+
+int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
+{
+ *ret = (int)InterlockedExchangeAdd((LONG volatile *)val, (LONG)amount)
+ + amount;
+ return 1;
+}
+
+int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret,
+ CRYPTO_RWLOCK *lock)
+{
+#if (defined(NO_INTERLOCKEDOR64))
+ if (lock == NULL || !CRYPTO_THREAD_write_lock(lock))
+ return 0;
+ *val |= op;
+ *ret = *val;
+
+ if (!CRYPTO_THREAD_unlock(lock))
+ return 0;
+
+ return 1;
+#else
+ *ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, (LONG64)op) | op;
+ return 1;
+#endif
+}
+
+int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock)
+{
+#if (defined(NO_INTERLOCKEDOR64))
+ if (lock == NULL || !CRYPTO_THREAD_read_lock(lock))
+ return 0;
+ *ret = *val;
+ if (!CRYPTO_THREAD_unlock(lock))
+ return 0;
+
+ return 1;
+#else
+ *ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, 0);
+ return 1;
+#endif
+}
+
+int openssl_init_fork_handlers(void)
+{
+ return 0;
+}
+
+int openssl_get_fork_id(void)
+{
+ return 0;
+}
+#endif
diff --git a/crypto/trace.c b/crypto/trace.c
new file mode 100644
index 000000000000..90a6350bebae
--- /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 || !OSSL_trace_enabled(category))
+ 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..99de0bb1a2e5 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the 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,60 @@ 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);
+ if (!PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificate,
+ V_ASN1_SEQUENCE, seq)) {
+ ASN1_STRING_free(seq);
+ return 0;
+ }
+ return 1;
+}
+
+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);
+ if (!PKCS7_add_signed_attribute(si, NID_id_smime_aa_signingCertificateV2,
+ V_ASN1_SEQUENCE, seq)) {
+ ASN1_STRING_free(seq);
+ return 0;
+ }
+ return 1;
+}
+
static int ts_RESP_sign(TS_RESP_CTX *ctx)
{
int ret = 0;
@@ -642,14 +691,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 +717,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 +764,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 +781,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 +795,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 +822,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 +886,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..fe7393bfd610 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-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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);
}
}
@@ -208,18 +207,23 @@ int UI_dup_input_string(UI *ui, const char *prompt, int flags,
char *result_buf, int minsize, int maxsize)
{
char *prompt_copy = NULL;
+ int ret;
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;
}
}
- return general_allocate_string(ui, prompt_copy, 1,
- UIT_PROMPT, flags, result_buf, minsize,
- maxsize, NULL);
+ ret = general_allocate_string(ui, prompt_copy, 1,
+ UIT_PROMPT, flags, result_buf, minsize,
+ maxsize, NULL);
+ if (ret <= 0)
+ OPENSSL_free(prompt_copy);
+
+ return ret;
}
int UI_add_verify_string(UI *ui, const char *prompt, int flags,
@@ -236,18 +240,22 @@ int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
const char *test_buf)
{
char *prompt_copy = NULL;
+ int ret;
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;
}
}
- return general_allocate_string(ui, prompt_copy, 1,
- UIT_VERIFY, flags, result_buf, minsize,
- maxsize, test_buf);
+ ret = general_allocate_string(ui, prompt_copy, 1,
+ UIT_VERIFY, flags, result_buf, minsize,
+ maxsize, test_buf);
+ if (ret <= 0)
+ OPENSSL_free(prompt_copy);
+ return ret;
}
int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
@@ -267,11 +275,12 @@ int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
char *action_desc_copy = NULL;
char *ok_chars_copy = NULL;
char *cancel_chars_copy = NULL;
+ int ret;
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 +288,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 +296,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,14 +304,19 @@ 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;
}
}
- return general_allocate_boolean(ui, prompt_copy, action_desc_copy,
- ok_chars_copy, cancel_chars_copy, 1,
- UIT_BOOLEAN, flags, result_buf);
+ ret = general_allocate_boolean(ui, prompt_copy, action_desc_copy,
+ ok_chars_copy, cancel_chars_copy, 1,
+ UIT_BOOLEAN, flags, result_buf);
+ if (ret <= 0)
+ goto err;
+
+ return ret;
+
err:
OPENSSL_free(prompt_copy);
OPENSSL_free(action_desc_copy);
@@ -320,17 +334,21 @@ int UI_add_info_string(UI *ui, const char *text)
int UI_dup_info_string(UI *ui, const char *text)
{
char *text_copy = NULL;
+ int ret;
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;
}
}
- return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL,
- 0, 0, NULL);
+ ret = general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL,
+ 0, 0, NULL);
+ if (ret <= 0)
+ OPENSSL_free(text_copy);
+ return ret;
}
int UI_add_error_string(UI *ui, const char *text)
@@ -342,44 +360,49 @@ int UI_add_error_string(UI *ui, const char *text)
int UI_dup_error_string(UI *ui, const char *text)
{
char *text_copy = NULL;
+ int ret;
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;
}
}
- return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL,
- 0, 0, NULL);
+
+ ret = general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL,
+ 0, 0, NULL);
+ if (ret <= 0)
+ OPENSSL_free(text_copy);
+ return ret;
}
-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 +431,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 +455,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 +468,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));
@@ -529,6 +552,10 @@ int UI_process(UI *ui)
ok = 0;
break;
}
+ } else {
+ ui->flags &= ~UI_FLAG_REDOABLE;
+ ok = -2;
+ goto err;
}
}
@@ -541,17 +568,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 +594,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 +603,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 +630,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 +713,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 +897,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 +907,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 +939,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..554bf7985659 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-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
@@ -32,7 +32,7 @@ int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt,
int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt,
int verify)
{
- int ok = 0;
+ int ok = -2;
UI *ui;
if (size < 1)
@@ -47,8 +47,6 @@ int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt,
ok = UI_process(ui);
UI_free(ui);
}
- if (ok > 0)
- ok = 0;
return ok;
}
@@ -71,12 +69,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,
@@ -105,17 +105,21 @@ static int ui_read(UI *ui, UI_STRING *uis)
switch (UI_get_string_type(uis)) {
case UIT_PROMPT:
{
- char result[PEM_BUFSIZE + 1];
+ int len;
+ char result[PEM_BUFSIZE + 1]; /* reserve one byte at the end */
const struct pem_password_cb_data *data =
UI_method_get_ex_data(UI_get_method(ui), ui_method_data_index);
int maxsize = UI_get_result_maxsize(uis);
- int len = data->cb(result,
- maxsize > PEM_BUFSIZE ? PEM_BUFSIZE : maxsize,
- data->rwflag, UI_get0_user_data(ui));
+ if (maxsize > PEM_BUFSIZE)
+ maxsize = PEM_BUFSIZE;
+ len = data->cb(result, maxsize, data->rwflag,
+ UI_get0_user_data(ui));
+ if (len > maxsize)
+ return -1;
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 +155,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..ad871966aa6e 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)
@@ -327,7 +348,8 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
/*
* we have added it to the cache so now pull it out again
*/
- X509_STORE_lock(xl->store_ctx);
+ if (!X509_STORE_lock(xl->store_ctx))
+ goto finish;
j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);
tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);
X509_STORE_unlock(xl->store_ctx);
@@ -339,7 +361,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 +376,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 +385,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 +421,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..e486fb0a9d94
--- /dev/null
+++ b/crypto/x509/by_store.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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>
+#include <openssl/store.h>
+#include "internal/cryptlib.h"
+#include "crypto/x509.h"
+#include "x509_local.h"
+
+typedef struct cached_store_st {
+ char *uri;
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ OSSL_STORE_CTX *ctx;
+} CACHED_STORE;
+
+DEFINE_STACK_OF(CACHED_STORE)
+
+/* Generic object loader, given expected type and criterion */
+static int cache_objects(X509_LOOKUP *lctx, CACHED_STORE *store,
+ const OSSL_STORE_SEARCH *criterion, int depth)
+{
+ int ok = 0;
+ OSSL_STORE_CTX *ctx = store->ctx;
+ X509_STORE *xstore = X509_LOOKUP_get_store(lctx);
+
+ if (ctx == NULL
+ && (ctx = OSSL_STORE_open_ex(store->uri, store->libctx, store->propq,
+ NULL, NULL, NULL, NULL, NULL)) == NULL)
+ return 0;
+ store->ctx = ctx;
+
+ /*
+ * 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) {
+ CACHED_STORE substore;
+
+ substore.uri = (char *)OSSL_STORE_INFO_get0_NAME(info);
+ substore.libctx = store->libctx;
+ substore.propq = store->propq;
+ substore.ctx = NULL;
+ ok = cache_objects(lctx, &substore, criterion, depth - 1);
+ }
+ } 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);
+ store->ctx = NULL;
+
+ return ok;
+}
+
+
+static void free_store(CACHED_STORE *store)
+{
+ if (store != NULL) {
+ OSSL_STORE_close(store->ctx);
+ OPENSSL_free(store->uri);
+ OPENSSL_free(store->propq);
+ OPENSSL_free(store);
+ }
+}
+
+static void by_store_free(X509_LOOKUP *ctx)
+{
+ STACK_OF(CACHED_STORE) *stores = X509_LOOKUP_get_method_data(ctx);
+ sk_CACHED_STORE_pop_free(stores, free_store);
+}
+
+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)
+{
+ /*
+ * In some cases below, failing to use the defaults shouldn't result in
+ * an error. |use_default| is used as the return code in those cases.
+ */
+ int use_default = argp == NULL;
+
+ 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(CACHED_STORE) *stores = X509_LOOKUP_get_method_data(ctx);
+ CACHED_STORE *store = OPENSSL_zalloc(sizeof(*store));
+
+ if (store == NULL) {
+ return 0;
+ }
+
+ store->uri = OPENSSL_strdup(argp);
+ store->libctx = libctx;
+ if (propq != NULL)
+ store->propq = OPENSSL_strdup(propq);
+ store->ctx = OSSL_STORE_open_ex(argp, libctx, propq, NULL, NULL,
+ NULL, NULL, NULL);
+ if (store->ctx == NULL
+ || (propq != NULL && store->propq == NULL)
+ || store->uri == NULL) {
+ free_store(store);
+ return use_default;
+ }
+
+ if (stores == NULL) {
+ stores = sk_CACHED_STORE_new_null();
+ if (stores != NULL)
+ X509_LOOKUP_set_method_data(ctx, stores);
+ }
+ if (stores == NULL || sk_CACHED_STORE_push(stores, store) <= 0) {
+ free_store(store);
+ return 0;
+ }
+ return 1;
+ }
+ case X509_L_LOAD_STORE: {
+ /* This is a shortcut for quick loading of specific containers */
+ CACHED_STORE store;
+
+ store.uri = (char *)argp;
+ store.libctx = libctx;
+ store.propq = (char *)propq;
+ store.ctx = NULL;
+ return cache_objects(ctx, &store, NULL, 0);
+ }
+ default:
+ /* Unsupported command */
+ return 0;
+ }
+
+ 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)
+{
+ STACK_OF(CACHED_STORE) *stores = X509_LOOKUP_get_method_data(ctx);
+ int i;
+ int ok = 0;
+
+ for (i = 0; i < sk_CACHED_STORE_num(stores); i++) {
+ ok = cache_objects(ctx, sk_CACHED_STORE_value(stores, i), criterion,
+ 1 /* depth */);
+
+ if (ok)
+ break;
+ }
+ return ok;
+}
+
+static int by_store_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret)
+{
+ OSSL_STORE_SEARCH *criterion =
+ OSSL_STORE_SEARCH_by_name((X509_NAME *)name); /* won't modify it */
+ int ok = by_store(ctx, type, criterion, ret);
+ 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;
+}
+
+/*
+ * 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 */
+ NULL, /* get_by_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/x509v3/pcy_cache.c b/crypto/x509/pcy_cache.c
index 04401bace8c5..1339f994aee1 100644
--- a/crypto/x509v3/pcy_cache.c
+++ b/crypto/x509/pcy_cache.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
@@ -35,14 +35,14 @@ static int policy_cache_create(X509 *x,
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);
+ 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 = policy_data_new(policy, NULL, crit);
+ data = ossl_policy_data_new(policy, NULL, crit);
if (data == NULL) {
- X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto just_cleanup;
}
/*
@@ -58,7 +58,7 @@ static int policy_cache_create(X509 *x,
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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto bad_policy;
}
data = NULL;
@@ -68,11 +68,11 @@ static int policy_cache_create(X509 *x,
bad_policy:
if (ret == -1)
x->ex_flags |= EXFLAG_INVALID_POLICY;
- policy_data_free(data);
+ 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, policy_data_free);
+ sk_X509_POLICY_DATA_pop_free(cache->data, ossl_policy_data_free);
cache->data = NULL;
}
return ret;
@@ -91,7 +91,7 @@ static int policy_cache_new(X509 *x)
return 1;
cache = OPENSSL_malloc(sizeof(*cache));
if (cache == NULL) {
- X509V3err(X509V3_F_POLICY_CACHE_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return 0;
}
cache->anyPolicy = NULL;
@@ -151,7 +151,7 @@ static int policy_cache_new(X509 *x)
if (i != -1)
goto bad_cache;
} else {
- i = policy_cache_set_mapping(x, ext_pmaps);
+ i = ossl_policy_cache_set_mapping(x, ext_pmaps);
if (i <= 0)
goto bad_cache;
}
@@ -175,20 +175,21 @@ static int policy_cache_new(X509 *x)
}
-void policy_cache_free(X509_POLICY_CACHE *cache)
+void ossl_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);
+ 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 *policy_cache_set(X509 *x)
+const X509_POLICY_CACHE *ossl_policy_cache_set(X509 *x)
{
if (x->policy_cache == NULL) {
- CRYPTO_THREAD_write_lock(x->lock);
+ if (!CRYPTO_THREAD_write_lock(x->lock))
+ return NULL;
policy_cache_new(x);
CRYPTO_THREAD_unlock(x->lock);
}
@@ -197,8 +198,8 @@ const X509_POLICY_CACHE *policy_cache_set(X509 *x)
}
-X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
- const ASN1_OBJECT *id)
+X509_POLICY_DATA *ossl_policy_cache_find_data(const X509_POLICY_CACHE *cache,
+ const ASN1_OBJECT *id)
{
int idx;
X509_POLICY_DATA tmp;
diff --git a/crypto/x509v3/pcy_data.c b/crypto/x509/pcy_data.c
index 8c7bc69576a4..6fb8f14ba8e8 100644
--- a/crypto/x509v3/pcy_data.c
+++ b/crypto/x509/pcy_data.c
@@ -1,7 +1,7 @@
/*
- * 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
* https://www.openssl.org/source/license.html
@@ -15,7 +15,7 @@
/* Policy Node routines */
-void policy_data_free(X509_POLICY_DATA *data)
+void ossl_policy_data_free(X509_POLICY_DATA *data)
{
if (data == NULL)
return;
@@ -35,8 +35,8 @@ void policy_data_free(X509_POLICY_DATA *data)
* source.
*/
-X509_POLICY_DATA *policy_data_new(POLICYINFO *policy,
- const ASN1_OBJECT *cid, int crit)
+X509_POLICY_DATA *ossl_policy_data_new(POLICYINFO *policy,
+ const ASN1_OBJECT *cid, int crit)
{
X509_POLICY_DATA *ret;
ASN1_OBJECT *id;
@@ -51,15 +51,15 @@ X509_POLICY_DATA *policy_data_new(POLICYINFO *policy,
id = NULL;
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- X509V3err(X509V3_F_POLICY_DATA_NEW, ERR_R_MALLOC_FAILURE);
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);
- X509V3err(X509V3_F_POLICY_DATA_NEW, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/x509v3/pcy_lib.c b/crypto/x509/pcy_lib.c
index 2e196b838ca2..c4740a0a30c5 100644
--- a/crypto/x509v3/pcy_lib.c
+++ b/crypto/x509/pcy_lib.c
@@ -1,7 +1,7 @@
/*
- * 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
@@ -69,7 +69,7 @@ int X509_policy_level_node_count(X509_POLICY_LEVEL *level)
return n;
}
-X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i)
+X509_POLICY_NODE *X509_policy_level_get0_node(const X509_POLICY_LEVEL *level, int i)
{
if (!level)
return NULL;
diff --git a/crypto/x509v3/pcy_local.h b/crypto/x509/pcy_local.h
index 5daf78de4585..523f3e35feeb 100644
--- a/crypto/x509v3/pcy_local.h
+++ b/crypto/x509/pcy_local.h
@@ -1,7 +1,7 @@
/*
- * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-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
@@ -111,6 +111,11 @@ struct X509_POLICY_LEVEL_st {
};
struct X509_POLICY_TREE_st {
+ /* The number of nodes in the tree */
+ size_t node_count;
+ /* The maximum number of nodes in the tree */
+ size_t node_maximum;
+
/* This is the tree 'level' data */
X509_POLICY_LEVEL *levels;
int nlevel;
@@ -135,33 +140,32 @@ struct X509_POLICY_TREE_st {
/* 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);
+X509_POLICY_DATA *ossl_policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
+ int crit);
+void ossl_policy_data_free(X509_POLICY_DATA *data);
-STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void);
+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);
-void policy_cache_init(void);
+STACK_OF(X509_POLICY_NODE) *ossl_policy_node_cmp_new(void);
-void policy_cache_free(X509_POLICY_CACHE *cache);
+void ossl_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 *ossl_policy_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 *ossl_policy_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);
+X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level,
+ X509_POLICY_DATA *data,
+ X509_POLICY_NODE *parent,
+ X509_POLICY_TREE *tree,
+ int extra_data);
+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 *policy_cache_set(X509 *x);
+const X509_POLICY_CACHE *ossl_policy_cache_set(X509 *x);
diff --git a/crypto/x509v3/pcy_map.c b/crypto/x509/pcy_map.c
index ae2a62c97787..60dfd1e3203b 100644
--- a/crypto/x509v3/pcy_map.c
+++ b/crypto/x509/pcy_map.c
@@ -1,7 +1,7 @@
/*
- * 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
@@ -19,7 +19,7 @@
* POLICY_MAPPINGS structure
*/
-int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
+int ossl_policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
{
POLICY_MAPPING *map;
X509_POLICY_DATA *data;
@@ -40,16 +40,16 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
}
/* Attempt to find matching policy data */
- data = policy_cache_find_data(cache, map->issuerDomainPolicy);
+ 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 = policy_data_new(NULL, map->issuerDomainPolicy,
- cache->anyPolicy->flags
- & POLICY_DATA_FLAG_CRITICAL);
+ 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;
@@ -59,7 +59,7 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
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);
+ ossl_policy_data_free(data);
goto bad_mapping;
}
} else
@@ -73,8 +73,6 @@ int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
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/x509/pcy_node.c
index e2d7b1532236..9b77e6e95e05 100644
--- a/crypto/x509v3/pcy_node.c
+++ b/crypto/x509/pcy_node.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-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 @@ static int node_cmp(const X509_POLICY_NODE *const *a,
return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
}
-STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void)
+STACK_OF(X509_POLICY_NODE) *ossl_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_NODE *ossl_policy_tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
+ const ASN1_OBJECT *id)
{
X509_POLICY_DATA n;
X509_POLICY_NODE l;
@@ -40,9 +40,9 @@ X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
}
-X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
- const X509_POLICY_NODE *parent,
- const ASN1_OBJECT *id)
+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;
@@ -56,21 +56,26 @@ X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
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 *ossl_policy_level_add_node(X509_POLICY_LEVEL *level,
+ X509_POLICY_DATA *data,
+ X509_POLICY_NODE *parent,
+ X509_POLICY_TREE *tree,
+ int extra_data)
{
X509_POLICY_NODE *node;
+ /* Verify that the tree isn't too large. This mitigates CVE-2023-0464 */
+ if (tree->node_maximum > 0 && tree->node_count >= tree->node_maximum)
+ return NULL;
+
node = OPENSSL_zalloc(sizeof(*node));
if (node == NULL) {
- X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
node->data = data;
node->parent = parent;
- if (level) {
+ if (level != NULL) {
if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
if (level->anyPolicy)
goto node_error;
@@ -78,42 +83,51 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
} else {
if (level->nodes == NULL)
- level->nodes = policy_node_cmp_new();
+ level->nodes = ossl_policy_node_cmp_new();
if (level->nodes == NULL) {
- X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto node_error;
}
}
}
- if (tree) {
+ if (extra_data) {
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;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto extra_data_error;
}
if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) {
- X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
- goto node_error;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto extra_data_error;
}
}
+ tree->node_count++;
if (parent)
parent->nchild++;
return node;
+ extra_data_error:
+ if (level != NULL) {
+ if (level->anyPolicy == node)
+ level->anyPolicy = NULL;
+ else
+ (void) sk_X509_POLICY_NODE_pop(level->nodes);
+ }
+
node_error:
- policy_node_free(node);
+ ossl_policy_node_free(node);
return NULL;
}
-void policy_node_free(X509_POLICY_NODE *node)
+void ossl_policy_node_free(X509_POLICY_NODE *node)
{
OPENSSL_free(node);
}
@@ -123,8 +137,8 @@ void policy_node_free(X509_POLICY_NODE *node)
* 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 ossl_policy_node_match(const X509_POLICY_LEVEL *lvl,
+ const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
{
int i;
ASN1_OBJECT *policy_oid;
diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509/pcy_tree.c
index 6e8322cbc5e3..2012810303ed 100644
--- a/crypto/x509v3/pcy_tree.c
+++ b/crypto/x509/pcy_tree.c
@@ -1,83 +1,91 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-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/cryptlib.h"
+#include <openssl/trace.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
+ * If the maximum number of nodes in the policy tree isn't defined, set it to
+ * a generous default of 1000 nodes.
+ *
+ * Defining this to be zero means unlimited policy tree growth which opens the
+ * door on CVE-2023-0464.
*/
+#ifndef OPENSSL_POLICY_TREE_NODES_MAX
+# define OPENSSL_POLICY_TREE_NODES_MAX 1000
+#endif
-#ifdef OPENSSL_POLICY_DEBUG
+static void exnode_free(X509_POLICY_NODE *node);
-static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
- X509_POLICY_NODE *node, int indent)
+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(err, " Not Mapped\n");
+ BIO_puts(channel, " Not Mapped\n");
else {
int i;
+
STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
ASN1_OBJECT *oid;
- BIO_puts(err, " Expected: ");
+ 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(err, ", ");
- i2a_ASN1_OBJECT(err, oid);
+ BIO_puts(channel, ", ");
+ i2a_ASN1_OBJECT(channel, oid);
}
- BIO_puts(err, "\n");
+ BIO_puts(channel, "\n");
}
}
-static void tree_print(char *str, X509_POLICY_TREE *tree,
+static void tree_print(BIO *channel,
+ 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);
+ 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(err, "Level %ld, flags = %x\n",
+ 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 *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);
+ 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(err, plev->anyPolicy, 2);
+ X509_POLICY_NODE_print(channel, plev->anyPolicy, 2);
}
- BIO_free(err);
}
-#endif
+
+#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:
@@ -118,7 +126,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
X509_check_purpose(x, -1, 0);
/* If cache is NULL, likely ENOMEM: return immediately */
- if (policy_cache_set(x) == NULL)
+ if (ossl_policy_cache_set(x) == NULL)
return X509_PCY_TREE_INTERNAL;
}
@@ -144,7 +152,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
return X509_PCY_TREE_INVALID;
/* Access the cache which we now know exists */
- cache = policy_cache_set(x);
+ cache = ossl_policy_cache_set(x);
if ((ret & X509_PCY_TREE_VALID) && cache->data == NULL)
ret = X509_PCY_TREE_EMPTY;
@@ -164,10 +172,13 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
/* If we get this far initialize the tree */
if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) {
- X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return X509_PCY_TREE_INTERNAL;
}
+ /* Limit the growth of the tree to mitigate CVE-2023-0464 */
+ tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX;
+
/*
* http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
*
@@ -177,15 +188,16 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
*/
if ((tree->levels = OPENSSL_zalloc(sizeof(*tree->levels)*(n+1))) == NULL) {
OPENSSL_free(tree);
- X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, 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)
+ if ((data = ossl_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);
+ if (ossl_policy_level_add_node(level, data, NULL, tree, 1) == NULL) {
+ ossl_policy_data_free(data);
goto bad_tree;
}
@@ -198,7 +210,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
uint32_t ex_flags = X509_get_extension_flags(x);
/* Access the cache which we now know exists */
- cache = policy_cache_set(x);
+ cache = ossl_policy_cache_set(x);
X509_up_ref(x);
(++level)->cert = x;
@@ -243,7 +255,8 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
* Return value: 1 on success, 0 otherwise
*/
static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
- X509_POLICY_DATA *data)
+ X509_POLICY_DATA *data,
+ X509_POLICY_TREE *tree)
{
X509_POLICY_LEVEL *last = curr - 1;
int i, matched = 0;
@@ -252,14 +265,14 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
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)
+ if (ossl_policy_node_match(last, node, data->valid_policy)) {
+ if (ossl_policy_level_add_node(curr, data, node, tree, 0) == NULL)
return 0;
matched = 1;
}
}
if (!matched && last->anyPolicy) {
- if (level_add_node(curr, data, last->anyPolicy, NULL) == NULL)
+ if (ossl_policy_level_add_node(curr, data, last->anyPolicy, tree, 0) == NULL)
return 0;
}
return 1;
@@ -272,7 +285,8 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
* Return value: 1 on success, 0 otherwise.
*/
static int tree_link_nodes(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache)
+ const X509_POLICY_CACHE *cache,
+ X509_POLICY_TREE *tree)
{
int i;
@@ -280,7 +294,7 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr,
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))
+ if (!tree_link_matching_nodes(curr, data, tree))
return 0;
}
return 1;
@@ -305,14 +319,14 @@ static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
* Create a new node with qualifiers from anyPolicy and id from unmatched
* node.
*/
- if ((data = policy_data_new(NULL, id, node_critical(node))) == NULL)
+ 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 (level_add_node(curr, data, node, tree) == NULL) {
- policy_data_free(data);
+ if (ossl_policy_level_add_node(curr, data, node, tree, 1) == NULL) {
+ ossl_policy_data_free(data);
return 0;
}
return 1;
@@ -344,7 +358,7 @@ static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
/* 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))
+ if (ossl_policy_level_find_node(curr, node, oid))
continue;
if (!tree_add_unmatched(curr, cache, oid, node, tree))
return 0;
@@ -373,7 +387,8 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
}
/* Finally add link to anyPolicy */
if (last->anyPolicy &&
- level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL) == NULL)
+ ossl_policy_level_add_node(curr, cache->anyPolicy,
+ last->anyPolicy, tree, 0) == NULL)
return 0;
return 1;
}
@@ -440,7 +455,7 @@ 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)
+ (*pnodes = ossl_policy_node_cmp_new()) == NULL)
return 0;
if (sk_X509_POLICY_NODE_find(*pnodes, pcy) >= 0)
return 1;
@@ -484,7 +499,7 @@ static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
curr = tree->levels;
for (i = 1; i < tree->nlevel; i++) {
/*
- * If no anyPolicy node on this this level it can't appear on lower
+ * If no anyPolicy node on this level it can't appear on lower
* levels so end search.
*/
if ((anyptr = curr->anyPolicy) == NULL)
@@ -541,7 +556,7 @@ static int tree_calculate_user_set(X509_POLICY_TREE *tree,
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);
+ node = ossl_policy_tree_find_sk(auth_nodes, oid);
if (!node) {
if (!anyPolicy)
continue;
@@ -549,21 +564,30 @@ static int tree_calculate_user_set(X509_POLICY_TREE *tree,
* Create a new node with policy ID from user set and qualifiers
* from anyPolicy.
*/
- extra = policy_data_new(NULL, oid, node_critical(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 = level_add_node(NULL, extra, anyPolicy->parent, tree);
+ node = ossl_policy_level_add_node(NULL, extra, anyPolicy->parent,
+ tree, 1);
+ if (node == NULL) {
+ ossl_policy_data_free(extra);
+ return 0;
+ }
}
if (!tree->user_policies) {
tree->user_policies = sk_X509_POLICY_NODE_new_null();
- if (!tree->user_policies)
- return 1;
+ if (!tree->user_policies) {
+ exnode_free(node);
+ return 0;
+ }
}
- if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
+ if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) {
+ exnode_free(node);
return 0;
+ }
}
return 1;
}
@@ -581,16 +605,14 @@ static int tree_evaluate(X509_POLICY_TREE *tree)
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))
+ cache = ossl_policy_cache_set(curr->cert);
+ if (!tree_link_nodes(curr, cache, tree))
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
+ TREE_PRINT("before tree_prune()", tree, curr);
ret = tree_prune(tree, curr);
if (ret != X509_PCY_TREE_VALID)
return ret;
@@ -617,11 +639,11 @@ void X509_policy_tree_free(X509_POLICY_TREE *tree)
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_NODE_pop_free(curr->nodes, ossl_policy_node_free);
+ ossl_policy_node_free(curr->anyPolicy);
}
- sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
+ sk_X509_POLICY_DATA_pop_free(tree->extra_data, ossl_policy_data_free);
OPENSSL_free(tree->levels);
OPENSSL_free(tree);
@@ -665,9 +687,7 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
}
ret = tree_evaluate(tree);
-#ifdef OPENSSL_POLICY_DEBUG
- tree_print("tree_evaluate()", tree, NULL);
-#endif
+ TREE_PRINT("tree_evaluate()", tree, NULL);
if (ret <= 0)
goto error;
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..63626c0d9810 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);
@@ -42,15 +42,15 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
EVP_PKEY *pkey;
STACK_OF(X509_EXTENSION) *exts;
char mlch = ' ';
- int nmindent = 0;
+ int nmindent = 0, printok = 0;
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mlch = '\n';
nmindent = 12;
}
- if (nmflags == X509_FLAG_COMPAT)
- nmindent = 16;
+ if (nmflags == XN_FLAG_COMPAT)
+ printok = 1;
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate Request:\n", 21) <= 0)
@@ -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 {
@@ -72,7 +72,7 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_REQ_get_subject_name(x),
- nmindent, nmflags) < 0)
+ nmindent, nmflags) < printok)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
@@ -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..5b0282bc132f 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,8 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
nmindent = 12;
}
- if (nmflags == X509_FLAG_COMPAT)
- nmindent = 16;
+ if (nmflags == XN_FLAG_COMPAT)
+ printok = 1;
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate:\n", 13) <= 0)
@@ -71,7 +71,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 +80,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 +130,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 +140,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 +153,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 +197,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 +227,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 +239,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 +269,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 +294,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 +312,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 +327,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 +390,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/x509v3/v3_addr.c b/crypto/x509/v3_addr.c
index f9c368bea405..20f3d2ba70de 100644
--- a/crypto/x509v3/v3_addr.c
+++ b/crypto/x509/v3_addr.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,7 @@
#include <openssl/x509v3.h>
#include "crypto/x509.h"
#include "ext_dat.h"
+#include "x509_local.h"
#ifndef OPENSSL_NO_RFC3779
@@ -396,11 +397,11 @@ 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();
+ IPAddressOrRange *aor;
if (prefixlen < 0 || prefixlen > (afilen * 8))
return 0;
- if (aor == NULL)
+ if ((aor = IPAddressOrRange_new()) == NULL)
return 0;
aor->type = IPAddressOrRange_addressPrefix;
if (aor->u.addressPrefix == NULL &&
@@ -690,6 +691,14 @@ static int IPAddressFamily_cmp(const IPAddressFamily *const *a_,
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.
*/
@@ -712,6 +721,10 @@ int X509v3_addr_is_canonical(IPAddrBlocks *addr)
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;
}
@@ -738,6 +751,9 @@ int X509v3_addr_is_canonical(IPAddrBlocks *addr)
return 0;
}
+ if (!IPAddressFamily_check_len(f))
+ return 0;
+
/*
* It's an IPAddressOrRanges sequence, check it.
*/
@@ -882,6 +898,10 @@ 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,
@@ -909,7 +929,7 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
int i;
if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -920,20 +940,19 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
const char *addr_chars = NULL;
int prefixlen, i1, i2, delim, length;
- if (!name_cmp(val->name, "IPv4")) {
+ if (!ossl_v3_name_cmp(val->name, "IPv4")) {
afi = IANA_AFI_IPV4;
- } else if (!name_cmp(val->name, "IPv6")) {
+ } else if (!ossl_v3_name_cmp(val->name, "IPv6")) {
afi = IANA_AFI_IPV6;
- } else if (!name_cmp(val->name, "IPv4-SAFI")) {
+ } else if (!ossl_v3_name_cmp(val->name, "IPv4-SAFI")) {
afi = IANA_AFI_IPV4;
safi = &safi_;
- } else if (!name_cmp(val->name, "IPv6-SAFI")) {
+ } else if (!ossl_v3_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);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR,
+ "%s", val->name);
goto err;
}
@@ -953,11 +972,15 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
* the other input values.
*/
if (safi != NULL) {
+ if (val->value == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
+ goto err;
+ }
*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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SAFI);
+ X509V3_conf_add_error_name_value(val);
goto err;
}
t += strspn(t, " \t");
@@ -966,7 +989,7 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
s = OPENSSL_strdup(val->value);
}
if (s == NULL) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -976,9 +999,8 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
*/
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE);
+ X509V3_conf_add_error_name_value(val);
goto err;
}
OPENSSL_free(s);
@@ -991,9 +1013,9 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
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);
+ 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;
}
@@ -1004,13 +1026,12 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
|| *t != '\0'
|| prefixlen > (length * 8)
|| prefixlen < 0) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_EXTENSION_VALUE_ERROR);
- X509V3_conf_err(val);
+ 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)) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
break;
@@ -1018,38 +1039,34 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_add_error_name_value(val);
goto err;
}
- if (a2i_ipadd(max, s + i1) != length) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_INVALID_IPADDRESS);
- X509V3_conf_err(val);
+ 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) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_EXTENSION_VALUE_ERROR);
- X509V3_conf_err(val);
+ 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)) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ 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)) {
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
break;
default:
- X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
- X509V3_R_EXTENSION_VALUE_ERROR);
- X509V3_conf_err(val);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_add_error_name_value(val);
goto err;
}
@@ -1073,7 +1090,7 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
/*
* OpenSSL dispatch
*/
-const X509V3_EXT_METHOD v3_addr = {
+const X509V3_EXT_METHOD ossl_v3_addr = {
NID_sbgp_ipAddrBlock, /* nid */
0, /* flags */
ASN1_ITEM_ref(IPAddrBlocks), /* template */
@@ -1122,7 +1139,7 @@ static int addr_contains(IPAddressOrRanges *parent,
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;
+ return 0;
for (;; p++) {
if (p >= sk_IPAddressOrRange_num(parent))
return 0;
@@ -1154,10 +1171,12 @@ int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b)
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);
+ 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))))
@@ -1169,19 +1188,19 @@ int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b)
/*
* 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)
+# 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.
@@ -1196,7 +1215,7 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx,
IPAddrBlocks *ext)
{
IPAddrBlocks *child = NULL;
- int i, j, ret = 1;
+ int i, j, ret = 0, rv;
X509 *x;
if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0)
@@ -1219,17 +1238,15 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx,
i = 0;
x = sk_X509_value(chain, i);
if ((ext = x->rfc3779_addr) == NULL)
- goto done;
+ 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) {
- X509V3err(X509V3_F_ADDR_VALIDATE_PATH_INTERNAL,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
if (ctx != NULL)
ctx->error = X509_V_ERR_OUT_OF_MEM;
- ret = 0;
goto done;
}
@@ -1244,6 +1261,10 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx,
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;
@@ -1258,6 +1279,7 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx,
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) {
@@ -1266,13 +1288,17 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx,
}
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))))
- sk_IPAddressFamily_set(child, j, fp);
+ (void)sk_IPAddressFamily_set(child, j, fp);
else
validation_err(X509_V_ERR_UNNESTED_RESOURCE);
}
@@ -1284,14 +1310,17 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx,
*/
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);
+ 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;
diff --git a/crypto/x509v3/v3_admis.c b/crypto/x509/v3_admis.c
index c8e75191bb3b..53259c29f569 100644
--- a/crypto/x509v3/v3_admis.c
+++ b/crypto/x509/v3_admis.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-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,7 +9,7 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/conf.h>
-#include <openssl/ossl_typ.h>
+#include <openssl/types.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
@@ -20,7 +20,6 @@
#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),
@@ -54,7 +53,7 @@ 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 = {
+const X509V3_EXT_METHOD ossl_v3_ext_admission = {
NID_x509ExtAdmission, /* .ext_nid = */
0, /* .ext_flags = */
ASN1_ITEM_ref(ADMISSION_SYNTAX), /* .it = */
@@ -68,11 +67,10 @@ const X509V3_EXT_METHOD v3_ext_admission = {
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;
+ NAMING_AUTHORITY *namingAuthority = (NAMING_AUTHORITY *) in;
if (namingAuthority == NULL)
return 0;
@@ -82,14 +80,14 @@ static int i2r_NAMING_AUTHORITY(const struct v3_ext_method *method, void *in,
&& namingAuthority->namingAuthorityUrl == NULL)
return 0;
- if (BIO_printf(bp, "%*snamingAuthority: ", ind, "") <= 0)
+ if (BIO_printf(bp, "%*snamingAuthority:\n", 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)
+ if (BIO_printf(bp, "%*s namingAuthorityId: ", ind, "") <= 0)
goto err;
OBJ_obj2txt(objbuf, sizeof(objbuf), namingAuthority->namingAuthorityId, 1);
@@ -131,9 +129,10 @@ static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
}
for (i = 0; i < sk_ADMISSIONS_num(admission->contentsOfAdmissions); i++) {
- ADMISSIONS* entry = sk_ADMISSIONS_value(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 (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
@@ -144,12 +143,12 @@ static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
}
if (entry->namingAuthority != NULL) {
- if (i2r_NAMING_AUTHORITY(method, entry->namingAuthority, bp, ind) <= 0)
+ if (i2r_NAMING_AUTHORITY(method, entry->namingAuthority, bp, ind + 2) <= 0)
goto err;
}
for (j = 0; j < sk_PROFESSION_INFO_num(entry->professionInfos); j++) {
- PROFESSION_INFO* pinfo = sk_PROFESSION_INFO_value(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;
@@ -162,7 +161,7 @@ static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
}
if (pinfo->namingAuthority != NULL) {
- if (i2r_NAMING_AUTHORITY(method, pinfo->namingAuthority, bp, ind + 2) <= 0)
+ if (i2r_NAMING_AUTHORITY(method, pinfo->namingAuthority, bp, ind + 4) <= 0)
goto err;
}
@@ -171,7 +170,7 @@ static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
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);
+ ASN1_STRING *val = sk_ASN1_STRING_value(pinfo->professionItems, k);
if (BIO_printf(bp, "%*s ", ind, "") <= 0
|| ASN1_STRING_print(bp, val) <= 0
@@ -184,7 +183,7 @@ static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
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);
+ ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(pinfo->professionOIDs, k);
const char *ln = OBJ_nid2ln(OBJ_obj2nid(obj));
char objbuf[128];
@@ -200,7 +199,7 @@ static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in,
return 1;
err:
- return -1;
+ return 0;
}
const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId(const NAMING_AUTHORITY *n)
@@ -208,31 +207,29 @@ 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)
+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)
+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)
+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)
+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)
+void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n, ASN1_STRING *t)
{
ASN1_IA5STRING_free(n->namingAuthorityText);
n->namingAuthorityText = t;
diff --git a/crypto/x509v3/v3_admis.h b/crypto/x509/v3_admis.h
index ea7632b3708d..1e82c0f4a33f 100644
--- a/crypto/x509v3/v3_admis.h
+++ b/crypto/x509/v3_admis.h
@@ -1,14 +1,14 @@
/*
* 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
*/
-#ifndef OSSL_CRYPTO_X509V3_V3_ADMIS_H
-# define OSSL_CRYPTO_X509V3_V3_ADMIS_H
+#ifndef OSSL_CRYPTO_X509_V3_ADMIS_H
+# define OSSL_CRYPTO_X509_V3_ADMIS_H
struct NamingAuthority_st {
ASN1_OBJECT* namingAuthorityId;
diff --git a/crypto/x509v3/v3_akeya.c b/crypto/x509/v3_akeya.c
index d6dd6bcb9b96..aae8c21e73c2 100644
--- a/crypto/x509v3/v3_akeya.c
+++ b/crypto/x509/v3_akeya.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/x509v3/v3_akey.c b/crypto/x509/v3_akid.c
index 33b1933d7228..43b515f50c49 100644
--- a/crypto/x509v3/v3_akey.c
+++ b/crypto/x509/v3_akid.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
@@ -13,6 +13,7 @@
#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,
@@ -23,7 +24,7 @@ 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 = {
+const X509V3_EXT_METHOD ossl_v3_akey_id = {
NID_authority_key_identifier,
X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
0, 0, 0, 0,
@@ -45,12 +46,13 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
- if (!X509V3_add_value("keyid", tmp, &extlist)) {
+ if (!X509V3_add_value((akeyid->issuer || akeyid->serial) ? "keyid" : NULL,
+ tmp, &extlist)) {
OPENSSL_free(tmp);
- X509V3err(X509V3_F_I2V_AUTHORITY_KEYID, ERR_R_X509_LIB);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB);
goto err;
}
OPENSSL_free(tmp);
@@ -58,7 +60,7 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
if (akeyid->issuer) {
tmpextlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
if (tmpextlist == NULL) {
- X509V3err(X509V3_F_I2V_AUTHORITY_KEYID, ERR_R_X509_LIB);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB);
goto err;
}
extlist = tmpextlist;
@@ -66,12 +68,11 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
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);
+ ERR_raise(ERR_LIB_X509V3, 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);
@@ -97,7 +98,7 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
STACK_OF(CONF_VALUE) *values)
{
char keyid = 0, issuer = 0;
- int i;
+ int i, n = sk_CONF_VALUE_num(values);
CONF_VALUE *cnf;
ASN1_OCTET_STRING *ikeyid = NULL;
X509_NAME *isname = NULL;
@@ -105,10 +106,18 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
GENERAL_NAME *gen = NULL;
ASN1_INTEGER *serial = NULL;
X509_EXTENSION *ext;
- X509 *cert;
- AUTHORITY_KEYID *akeyid;
+ X509 *issuer_cert;
+ int same_issuer, ss;
+ AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
- for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ 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;
@@ -119,51 +128,71 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
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;
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNKNOWN_OPTION,
+ "name=%s", cnf->name);
+ goto err;
}
}
- 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 (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
+ return akeyid;
- if (keyid) {
- i = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
- if ((i >= 0) && (ext = X509_get_ext(cert, i)))
+ 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 (keyid == 2 && !ikeyid) {
- X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,
- X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
- return NULL;
+ 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 && !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);
+ 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 ((akeyid = AUTHORITY_KEYID_new()) == NULL)
- goto err;
-
- if (isname) {
+ if (isname != NULL) {
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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
gen->type = GEN_DIRNAME;
@@ -184,5 +213,6 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
X509_NAME_free(isname);
ASN1_INTEGER_free(serial);
ASN1_OCTET_STRING_free(ikeyid);
+ AUTHORITY_KEYID_free(akeyid);
return NULL;
}
diff --git a/crypto/x509v3/v3_asid.c b/crypto/x509/v3_asid.c
index 8e9e919804d0..c2b6f8a660df 100644
--- a/crypto/x509v3/v3_asid.c
+++ b/crypto/x509/v3_asid.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 @@
#include "crypto/x509.h"
#include <openssl/bn.h>
#include "ext_dat.h"
+#include "x509_local.h"
#ifndef OPENSSL_NO_RFC3779
@@ -168,8 +169,11 @@ int X509v3_asid_add_inherit(ASIdentifiers *asid, int which)
if (*choice == NULL) {
if ((*choice = ASIdentifierChoice_new()) == NULL)
return 0;
- if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL)
+ if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) {
+ ASIdentifierChoice_free(*choice);
+ *choice = NULL;
return 0;
+ }
(*choice)->type = ASIdentifierChoice_inherit;
}
return (*choice)->type == ASIdentifierChoice_inherit;
@@ -195,18 +199,23 @@ int X509v3_asid_add_id_or_range(ASIdentifiers *asid,
default:
return 0;
}
- if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit)
+ if (*choice != NULL && (*choice)->type != ASIdentifierChoice_asIdsOrRanges)
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)
+ if ((*choice)->u.asIdsOrRanges == NULL) {
+ ASIdentifierChoice_free(*choice);
+ *choice = NULL;
return 0;
+ }
(*choice)->type = ASIdentifierChoice_asIdsOrRanges;
}
if ((aor = ASIdOrRange_new()) == NULL)
return 0;
+ if (!sk_ASIdOrRange_reserve((*choice)->u.asIdsOrRanges, 1))
+ goto err;
if (max == NULL) {
aor->type = ASIdOrRange_id;
aor->u.id = min;
@@ -219,7 +228,8 @@ int X509v3_asid_add_id_or_range(ASIdentifiers *asid,
ASN1_INTEGER_free(aor->u.range->max);
aor->u.range->max = max;
}
- if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor)))
+ /* Cannot fail due to the reservation above */
+ if (!ossl_assert(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor)))
goto err;
return 1;
@@ -300,16 +310,14 @@ static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice)
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);
+ 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;
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -373,8 +381,7 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
*/
if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) {
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- X509V3_R_EXTENSION_VALUE_ERROR);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
return 0;
}
@@ -414,8 +421,7 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
* Check for overlaps.
*/
if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) {
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- X509V3_R_EXTENSION_VALUE_ERROR);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
goto done;
}
@@ -425,16 +431,14 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
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);
+ 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;
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -446,8 +450,7 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
switch (a->type) {
case ASIdOrRange_id:
if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) {
- X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto done;
}
r->min = a_min;
@@ -523,7 +526,7 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
int i;
if ((asid = ASIdentifiers_new()) == NULL) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -534,14 +537,18 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
/*
* Figure out whether this is an AS or an RDI.
*/
- if (!name_cmp(val->name, "AS")) {
+ if (!ossl_v3_name_cmp(val->name, "AS")) {
which = V3_ASID_ASNUM;
- } else if (!name_cmp(val->name, "RDI")) {
+ } else if (!ossl_v3_name_cmp(val->name, "RDI")) {
which = V3_ASID_RDI;
} else {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
- X509V3_R_EXTENSION_NAME_ERROR);
- X509V3_conf_err(val);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR);
+ X509V3_conf_add_error_name_value(val);
+ goto err;
+ }
+
+ if (val->value == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
goto err;
}
@@ -551,9 +558,8 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE);
+ X509V3_conf_add_error_name_value(val);
goto err;
}
@@ -567,18 +573,16 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
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);
+ 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') {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
- X509V3_R_INVALID_ASRANGE);
- X509V3_conf_err(val);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_ASRANGE);
+ X509V3_conf_add_error_name_value(val);
goto err;
}
}
@@ -588,13 +592,13 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
*/
if (!is_range) {
if (!X509V3_get_value_int(val, &min)) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
s[i1] = '\0';
@@ -602,17 +606,16 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
max = s2i_ASN1_INTEGER(NULL, s + i2);
OPENSSL_free(s);
if (min == NULL || max == NULL) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
if (ASN1_INTEGER_cmp(min, max) > 0) {
- X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
- X509V3_R_EXTENSION_VALUE_ERROR);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
min = max = NULL;
@@ -635,7 +638,7 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
/*
* OpenSSL dispatch.
*/
-const X509V3_EXT_METHOD v3_asid = {
+const X509V3_EXT_METHOD ossl_v3_asid = {
NID_sbgp_autonomousSysNum, /* nid */
0, /* flags */
ASN1_ITEM_ref(ASIdentifiers), /* template */
diff --git a/crypto/x509v3/v3_bcons.c b/crypto/x509/v3_bcons.c
index 3bbf15550d32..6e7a165f26e8 100644
--- a/crypto/x509v3/v3_bcons.c
+++ b/crypto/x509/v3_bcons.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
@@ -14,6 +14,7 @@
#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,
@@ -23,7 +24,7 @@ static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *values);
-const X509V3_EXT_METHOD v3_bcons = {
+const X509V3_EXT_METHOD ossl_v3_bcons = {
NID_basic_constraints, 0,
ASN1_ITEM_ref(BASIC_CONSTRAINTS),
0, 0, 0, 0,
@@ -60,7 +61,7 @@ static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
int i;
if ((bcons = BASIC_CONSTRAINTS_new()) == NULL) {
- X509V3err(X509V3_F_V2I_BASIC_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
@@ -72,8 +73,8 @@ static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NAME);
+ X509V3_conf_add_error_name_value(val);
goto err;
}
}
diff --git a/crypto/x509v3/v3_bitst.c b/crypto/x509/v3_bitst.c
index 4802116ba0d4..b53c5ba3ecd3 100644
--- a/crypto/x509v3/v3_bitst.c
+++ b/crypto/x509/v3_bitst.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
@@ -38,9 +38,9 @@ static BIT_STRING_BITNAME key_usage_type_table[] = {
{-1, NULL, NULL}
};
-const X509V3_EXT_METHOD v3_nscert =
+const X509V3_EXT_METHOD ossl_v3_nscert =
EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
-const X509V3_EXT_METHOD v3_key_usage =
+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,
@@ -64,7 +64,7 @@ ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
int i;
BIT_STRING_BITNAME *bnam;
if ((bs = ASN1_BIT_STRING_new()) == NULL) {
- X509V3err(X509V3_F_V2I_ASN1_BIT_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
@@ -73,8 +73,7 @@ ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
ASN1_BIT_STRING_free(bs);
return NULL;
}
@@ -82,9 +81,8 @@ ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
}
}
if (!bnam->lname) {
- X509V3err(X509V3_F_V2I_ASN1_BIT_STRING,
- X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT);
- X509V3_conf_err(val);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT,
+ "%s", val->name);
ASN1_BIT_STRING_free(bs);
return NULL;
}
diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509/v3_conf.c
index e93de3454604..1c11d671b2ed 100644
--- a/crypto/x509v3/v3_conf.c
+++ b/crypto/x509/v3_conf.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
@@ -30,33 +30,43 @@ 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)
+
+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) {
- X509V3err(X509V3_F_X509V3_EXT_NCONF, X509V3_R_ERROR_IN_EXTENSION);
- ERR_add_error_data(4, "name=", name, ", value=", value);
+ 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;
}
-/* CONF *conf: Config file */
-/* char *value: Value */
+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),
@@ -75,11 +85,11 @@ static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
void *ext_struc;
if (ext_nid == NID_undef) {
- X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION_NAME);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION);
return NULL;
}
/* Now get internal extension representation based on type */
@@ -89,10 +99,8 @@ static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
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);
+ 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;
@@ -107,15 +115,14 @@ static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
return NULL;
} else if (method->r2i) {
if (!ctx->db || !ctx->db_meth) {
- X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_NO_CONFIG_DATABASE);
+ ERR_raise(ERR_LIB_X509V3, 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));
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED,
+ "name=%s", OBJ_nid2sn(ext_nid));
return NULL;
}
@@ -135,6 +142,7 @@ static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
int ext_len;
ASN1_OCTET_STRING *ext_oct = NULL;
X509_EXTENSION *ext;
+
/* Convert internal representation to DER */
if (method->it) {
ext_der = NULL;
@@ -146,6 +154,8 @@ static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
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;
@@ -165,7 +175,7 @@ static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
return ext;
merr:
- X509V3err(X509V3_F_DO_EXT_I2D, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ext_der);
ASN1_OCTET_STRING_free(ext_oct);
return NULL;
@@ -179,7 +189,7 @@ 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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNKNOWN_EXTENSION);
return NULL;
}
return do_ext_i2d(method, ext_nid, crit, ext_struc);
@@ -189,6 +199,7 @@ X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc)
static int v3_check_critical(const char **value)
{
const char *p = *value;
+
if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
return 0;
p += 9;
@@ -203,6 +214,7 @@ 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;
@@ -230,9 +242,8 @@ static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
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);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR,
+ "name=%s", ext);
goto err;
}
@@ -242,14 +253,13 @@ static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
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);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR,
+ "value=%s", value);
goto err;
}
if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
- X509V3err(X509V3_F_V3_GENERIC_EXTENSION, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -272,6 +282,7 @@ static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx,
{
ASN1_TYPE *typ;
unsigned char *ext_der = NULL;
+
typ = ASN1_generate_v3(value, ctx);
if (typ == NULL)
return NULL;
@@ -284,19 +295,17 @@ 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);
- }
+ 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.
+ * 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)
{
@@ -309,11 +318,12 @@ int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
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)
+ if ((ext = X509V3_EXT_nconf_int(conf, ctx, val->section,
+ val->name, val->value)) == NULL)
return 0;
- if (ctx->flags == X509V3_CTX_REPLACE)
- delete_ext(*sk, ext);
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;
@@ -325,44 +335,45 @@ int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
}
/*
- * Convenience functions to add extensions to a certificate, CRL and request
+ * 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)
+ if (cert != NULL)
sk = &cert->cert_info.extensions;
return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
}
-/* Same as above but for a CRL */
-
+/*
+ * 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)
+ if (crl != NULL)
sk = &crl->crl.extensions;
return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
}
-/* Add extensions to certificate request */
-
+/*
+ * 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) *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;
+ 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 */
@@ -370,7 +381,7 @@ int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_OPERATION_NOT_DEFINED);
return NULL;
}
if (ctx->db_meth->get_string)
@@ -381,8 +392,7 @@ 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)
{
if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) {
- X509V3err(X509V3_F_X509V3_GET_SECTION,
- X509V3_R_OPERATION_NOT_DEFINED);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_OPERATION_NOT_DEFINED);
return NULL;
}
if (ctx->db_meth->get_section)
@@ -425,6 +435,10 @@ static X509V3_CONF_METHOD nconf_method = {
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;
}
@@ -432,11 +446,33 @@ void X509V3_set_nconf(X509V3_CTX *ctx, CONF *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->crl = crl;
ctx->subject_req = req;
- ctx->flags = flags;
+ 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 */
@@ -444,19 +480,31 @@ void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
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);
+ 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;
}
-/* 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);
+ 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)
@@ -478,6 +526,10 @@ static X509V3_CONF_METHOD conf_lhash_method = {
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;
}
@@ -485,9 +537,16 @@ void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *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);
+ 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 */
@@ -495,9 +554,16 @@ int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
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);
+ 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 */
@@ -505,7 +571,14 @@ int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
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);
+ 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/x509v3/v3_cpols.c b/crypto/x509/v3_cpols.c
index 09804b58482c..5353a6916761 100644
--- a/crypto/x509v3/v3_cpols.c
+++ b/crypto/x509/v3_cpols.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
@@ -14,6 +14,7 @@
#include <openssl/asn1t.h>
#include <openssl/x509v3.h>
+#include "x509_local.h"
#include "pcy_local.h"
#include "ext_dat.h"
@@ -34,7 +35,7 @@ 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 = {
+const X509V3_EXT_METHOD ossl_v3_cpols = {
NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
0, 0, 0, 0,
0, 0,
@@ -98,24 +99,22 @@ static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
int i, ia5org;
if (vals == NULL) {
- X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ 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 || !cnf->name) {
- X509V3err(X509V3_F_R2I_CERTPOL,
- X509V3_R_INVALID_POLICY_IDENTIFIER);
- X509V3_conf_err(cnf);
+ 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;
@@ -124,11 +123,11 @@ static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
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);
+ 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);
@@ -137,22 +136,22 @@ static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
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);
+ 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);
- X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -178,15 +177,15 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx,
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
X509V3_conf_err(cnf);
goto err;
}
pol->policyid = pobj;
- } else if (!name_cmp(cnf->name, "CPS")) {
+ } else if (!ossl_v3_name_cmp(cnf->name, "CPS")) {
if (pol->qualifiers == NULL)
pol->qualifiers = sk_POLICYQUALINFO_new_null();
if ((qual = POLICYQUALINFO_new()) == NULL)
@@ -194,7 +193,7 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx,
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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL)
@@ -202,17 +201,16 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx,
if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
strlen(cnf->value)))
goto merr;
- } else if (!name_cmp(cnf->name, "userNotice")) {
+ } else if (!ossl_v3_name_cmp(cnf->name, "userNotice")) {
STACK_OF(CONF_VALUE) *unot;
if (*cnf->value != '@') {
- X509V3err(X509V3_F_POLICY_SECTION,
- X509V3_R_EXPECTED_A_SECTION_NAME);
+ 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) {
- X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SECTION);
X509V3_conf_err(cnf);
goto err;
@@ -221,26 +219,25 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx,
X509V3_section_free(ctx, unot);
if (!qual)
goto err;
- if (!pol->qualifiers)
+ if (pol->qualifiers == NULL)
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);
-
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OPTION);
X509V3_conf_err(cnf);
goto err;
}
}
- if (!pol->policyid) {
- X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER);
+ if (pol->policyid == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_POLICY_IDENTIFIER);
goto err;
}
return pol;
merr:
- X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
err:
POLICYINFO_free(pol);
@@ -293,7 +290,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((not = USERNOTICE_new()) == NULL)
@@ -301,6 +298,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
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);
@@ -313,6 +311,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
goto merr;
} else if (strcmp(cnf->name, "organization") == 0) {
NOTICEREF *nref;
+
if (!not->noticeref) {
if ((nref = NOTICEREF_new()) == NULL)
goto merr;
@@ -328,6 +327,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
goto merr;
} else if (strcmp(cnf->name, "noticeNumbers") == 0) {
NOTICEREF *nref;
+
STACK_OF(CONF_VALUE) *nos;
if (!not->noticeref) {
if ((nref = NOTICEREF_new()) == NULL)
@@ -337,8 +337,8 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
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);
+ 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;
}
@@ -347,23 +347,22 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
if (!ret)
goto err;
} else {
- X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION);
- X509V3_conf_err(cnf);
+ 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)) {
- X509V3err(X509V3_F_NOTICE_SECTION,
- X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
goto err;
}
return qual;
merr:
- X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
err:
POLICYQUALINFO_free(qual);
@@ -380,7 +379,7 @@ static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NUMBER);
goto err;
}
if (!sk_ASN1_INTEGER_push(nnums, aint))
@@ -390,7 +389,7 @@ static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
merr:
ASN1_INTEGER_free(aint);
- X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
err:
return 0;
@@ -403,12 +402,15 @@ static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
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);
- BIO_puts(out, "\n");
- if (pinfo->qualifiers)
+ if (pinfo->qualifiers) {
+ BIO_puts(out, "\n");
print_qualifiers(out, pinfo->qualifiers, indent + 2);
+ }
}
return 1;
}
@@ -419,10 +421,12 @@ static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
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\n", indent, "",
+ BIO_printf(out, "%*sCPS: %.*s", indent, "",
qualinfo->d.cpsuri->length,
qualinfo->d.cpsuri->data);
break;
@@ -436,7 +440,6 @@ static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
i2a_ASN1_OBJECT(out, qualinfo->pqualid);
- BIO_puts(out, "\n");
break;
}
}
@@ -469,10 +472,11 @@ static void print_notice(BIO *out, USERNOTICE *notice, int indent)
OPENSSL_free(tmp);
}
}
- BIO_puts(out, "\n");
+ if (notice->exptext)
+ BIO_puts(out, "\n");
}
if (notice->exptext)
- BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "",
+ BIO_printf(out, "%*sExplicit Text: %.*s", indent, "",
notice->exptext->length,
notice->exptext->data);
}
@@ -487,8 +491,10 @@ void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
BIO_puts(out, "\n");
BIO_printf(out, "%*s%s\n", indent + 2, "",
node_data_critical(dat) ? "Critical" : "Non Critical");
- if (dat->qualifier_set)
+ 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/x509v3/v3_crld.c b/crypto/x509/v3_crld.c
index 4854748ffb51..07c8379d3521 100644
--- a/crypto/x509v3/v3_crld.c
+++ b/crypto/x509/v3_crld.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,14 @@
#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 v3_crld = {
+const X509V3_EXT_METHOD ossl_v3_crld = {
NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
0, 0, 0, 0,
0, 0,
@@ -32,7 +33,7 @@ const X509V3_EXT_METHOD v3_crld = {
NULL
};
-const X509V3_EXT_METHOD v3_freshest_crl = {
+const X509V3_EXT_METHOD ossl_v3_freshest_crl = {
NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
0, 0, 0, 0,
0, 0,
@@ -52,7 +53,7 @@ static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx,
else
gnsect = X509V3_parse_list(sect);
if (!gnsect) {
- X509V3err(X509V3_F_GNAMES_FROM_SECTNAME, X509V3_R_SECTION_NOT_FOUND);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND);
return NULL;
}
gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
@@ -69,6 +70,11 @@ static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
STACK_OF(GENERAL_NAME) *fnm = NULL;
STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
+ if (cnf->value == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
+ goto err;
+ }
+
if (strncmp(cnf->name, "fullname", 9) == 0) {
fnm = gnames_from_sectname(ctx, cnf->value);
if (!fnm)
@@ -82,8 +88,8 @@ static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
return -1;
dnsect = X509V3_get_section(ctx, cnf->value);
if (!dnsect) {
- X509V3err(X509V3_F_SET_DIST_POINT_NAME,
- X509V3_R_SECTION_NOT_FOUND);
+ 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);
@@ -98,16 +104,14 @@ static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
*/
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
goto err;
}
} else
return 0;
if (*pdp) {
- X509V3err(X509V3_F_SET_DIST_POINT_NAME,
- X509V3_R_DISTPOINT_ALREADY_SET);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
goto err;
}
@@ -168,7 +172,7 @@ static int set_reasons(ASN1_BIT_STRING **preas, char *value)
break;
}
}
- if (!pbn->lname)
+ if (pbn->lname == NULL)
goto err;
}
ret = 1;
@@ -222,7 +226,7 @@ static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
goto err;
} else if (strcmp(cnf->name, "CRLissuer") == 0) {
point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
- if (!point->CRLissuer)
+ if (point->CRLissuer == NULL)
goto err;
}
}
@@ -251,14 +255,14 @@ static void *v2i_crld(const X509V3_EXT_METHOD *method,
DIST_POINT *point;
cnf = sk_CONF_VALUE_value(nval, i);
- if (!cnf->value) {
+ 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)
+ if (point == NULL)
goto err;
sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */
} else {
@@ -282,7 +286,7 @@ static void *v2i_crld(const X509V3_EXT_METHOD *method,
return crld;
merr:
- X509V3err(X509V3_F_V2I_CRLD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
err:
GENERAL_NAME_free(gen);
GENERAL_NAMES_free(gens);
@@ -346,7 +350,7 @@ static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *nval);
-const X509V3_EXT_METHOD v3_idp = {
+const X509V3_EXT_METHOD ossl_v3_idp = {
NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
ASN1_ITEM_ref(ISSUING_DIST_POINT),
0, 0, 0, 0,
@@ -392,15 +396,15 @@ static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
if (!set_reasons(&idp->onlysomereasons, val))
goto err;
} else {
- X509V3err(X509V3_F_V2I_IDP, X509V3_R_INVALID_NAME);
- X509V3_conf_err(cnf);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NAME);
+ X509V3_conf_add_error_name_value(cnf);
goto err;
}
}
return idp;
merr:
- X509V3err(X509V3_F_V2I_IDP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
err:
ISSUING_DIST_POINT_free(idp);
return NULL;
@@ -410,9 +414,10 @@ 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));
- BIO_puts(out, "\n");
}
return 1;
}
@@ -463,7 +468,8 @@ static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
DIST_POINT *point;
int i;
for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
- BIO_puts(out, "\n");
+ if (i > 0)
+ BIO_puts(out, "\n");
point = sk_DIST_POINT_value(crld, i);
if (point->distpoint)
print_distpoint(out, point->distpoint, indent);
@@ -477,30 +483,31 @@ static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
return 1;
}
-int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
+/* 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 || (dpn->type != 1))
+
+ 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)
+ 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)) {
- X509_NAME_free(dpn->dpname);
- dpn->dpname = NULL;
- return 0;
- }
+ 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) {
- X509_NAME_free(dpn->dpname);
- dpn->dpname = NULL;
- return 0;
- }
- return 1;
+ 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/x509v3/v3_enum.c b/crypto/x509/v3_enum.c
index 3b0f197444af..b73a6d55162b 100644
--- a/crypto/x509v3/v3_enum.c
+++ b/crypto/x509/v3_enum.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
@@ -29,7 +29,7 @@ static ENUMERATED_NAMES crl_reasons[] = {
{-1, NULL, NULL}
};
-const X509V3_EXT_METHOD v3_crl_reason = {
+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,
diff --git a/crypto/x509v3/v3_extku.c b/crypto/x509/v3_extku.c
index 91b24376ed8a..4f2a86bdcb2b 100644
--- a/crypto/x509v3/v3_extku.c
+++ b/crypto/x509/v3_extku.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
@@ -21,7 +21,7 @@ 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 = {
+const X509V3_EXT_METHOD ossl_v3_ext_ku = {
NID_ext_key_usage, 0,
ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
0, 0, 0, 0,
@@ -33,7 +33,7 @@ const X509V3_EXT_METHOD v3_ext_ku = {
};
/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */
-const X509V3_EXT_METHOD v3_ocsp_accresp = {
+const X509V3_EXT_METHOD ossl_v3_ocsp_accresp = {
NID_id_pkix_OCSP_acceptableResponses, 0,
ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
0, 0, 0, 0,
@@ -79,7 +79,7 @@ static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
extku = sk_ASN1_OBJECT_new_reserve(NULL, num);
if (extku == NULL) {
- X509V3err(X509V3_F_V2I_EXTENDED_KEY_USAGE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
sk_ASN1_OBJECT_free(extku);
return NULL;
}
@@ -92,9 +92,8 @@ static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
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);
+ 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 */
diff --git a/crypto/x509v3/v3_genn.c b/crypto/x509/v3_genn.c
index fd307c43cf20..1f67bf2f63ab 100644
--- a/crypto/x509v3/v3_genn.c
+++ b/crypto/x509/v3_genn.c
@@ -1,7 +1,7 @@
/*
* 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
@@ -51,7 +51,7 @@ ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
-GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a)
+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,
diff --git a/crypto/x509v3/v3_ia5.c b/crypto/x509/v3_ia5.c
index c1170d46161e..6722b6c01f05 100644
--- a/crypto/x509v3/v3_ia5.c
+++ b/crypto/x509/v3_ia5.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
@@ -14,7 +14,7 @@
#include <openssl/x509v3.h>
#include "ext_dat.h"
-const X509V3_EXT_METHOD v3_ns_ia5_list[8] = {
+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),
@@ -29,10 +29,10 @@ char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5)
{
char *tmp;
- if (!ia5 || !ia5->length)
+ if (ia5 == NULL || ia5->length <= 0)
return NULL;
if ((tmp = OPENSSL_malloc(ia5->length + 1)) == NULL) {
- X509V3err(X509V3_F_I2S_ASN1_IA5STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
memcpy(tmp, ia5->data, ia5->length);
@@ -44,9 +44,8 @@ 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);
+ if (str == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
return NULL;
}
if ((ia5 = ASN1_IA5STRING_new()) == NULL)
@@ -60,6 +59,6 @@ ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
#endif /* CHARSET_EBCDIC */
return ia5;
err:
- X509V3err(X509V3_F_S2I_ASN1_IA5STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
diff --git a/crypto/x509v3/v3_info.c b/crypto/x509/v3_info.c
index 7af9e23ae8c9..5f21ce11e7d5 100644
--- a/crypto/x509v3/v3_info.c
+++ b/crypto/x509/v3_info.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
@@ -25,7 +25,7 @@ static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
STACK_OF(CONF_VALUE)
*nval);
-const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE,
+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,
@@ -35,7 +35,7 @@ const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE,
NULL
};
-const X509V3_EXT_METHOD v3_sinfo = { NID_sinfo_access, X509V3_EXT_MULTILINE,
+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,
@@ -91,7 +91,7 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(
return tret;
err:
- X509V3err(X509V3_F_I2V_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE);
+ 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;
@@ -106,48 +106,42 @@ static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
AUTHORITY_INFO_ACCESS *ainfo = NULL;
CONF_VALUE *cnf, ctmp;
ACCESS_DESCRIPTION *acc;
- int i, objlen;
+ int i;
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);
+ 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) {
- X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS,
- ERR_R_MALLOC_FAILURE);
+ 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) {
- X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS,
- X509V3_R_INVALID_SYNTAX);
+ if (ptmp == NULL) {
+ ERR_raise(ERR_LIB_X509V3, 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);
+ 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) {
- X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS,
- X509V3_R_BAD_OBJECT);
- ERR_add_error_data(2, "value=", objtmp);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT,
+ "value=%s", objtmp);
OPENSSL_free(objtmp);
goto err;
}
OPENSSL_free(objtmp);
-
}
return ainfo;
err:
diff --git a/crypto/x509v3/v3_int.c b/crypto/x509/v3_int.c
index 690c90e8f96e..dae26a5ba9d7 100644
--- a/crypto/x509v3/v3_int.c
+++ b/crypto/x509/v3_int.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,7 +12,7 @@
#include <openssl/x509v3.h>
#include "ext_dat.h"
-const X509V3_EXT_METHOD v3_crl_num = {
+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,
@@ -20,7 +20,7 @@ const X509V3_EXT_METHOD v3_crl_num = {
0, 0, 0, 0, NULL
};
-const X509V3_EXT_METHOD v3_delta_crl = {
+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,
@@ -34,7 +34,7 @@ static void *s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx,
return s2i_ASN1_INTEGER(meth, value);
}
-const X509V3_EXT_METHOD v3_inhibit_anyp = {
+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,
diff --git a/crypto/x509/v3_ist.c b/crypto/x509/v3_ist.c
new file mode 100644
index 000000000000..96c40a3961a2
--- /dev/null
+++ b/crypto/x509/v3_ist.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the 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
+ || cnf->value == NULL
+ || !ASN1_STRING_set(ist->signTool, cnf->value, strlen(cnf->value))) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else if (strcmp(cnf->name, "cATool") == 0) {
+ ist->cATool = ASN1_UTF8STRING_new();
+ if (ist->cATool == NULL
+ || cnf->value == NULL
+ || !ASN1_STRING_set(ist->cATool, cnf->value, strlen(cnf->value))) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else if (strcmp(cnf->name, "signToolCert") == 0) {
+ ist->signToolCert = ASN1_UTF8STRING_new();
+ if (ist->signToolCert == NULL
+ || cnf->value == NULL
+ || !ASN1_STRING_set(ist->signToolCert, cnf->value, strlen(cnf->value))) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else if (strcmp(cnf->name, "cAToolCert") == 0) {
+ ist->cAToolCert = ASN1_UTF8STRING_new();
+ if (ist->cAToolCert == NULL
+ || cnf->value == NULL
+ || !ASN1_STRING_set(ist->cAToolCert, cnf->value, strlen(cnf->value))) {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else {
+ ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_INVALID_ARGUMENT);
+ goto err;
+ }
+ }
+ return ist;
+
+err:
+ ISSUER_SIGN_TOOL_free(ist);
+ return NULL;
+}
+
+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/x509v3/v3_lib.c b/crypto/x509/v3_lib.c
index ea88ff2acd22..6d91df99550f 100644
--- a/crypto/x509v3/v3_lib.c
+++ b/crypto/x509/v3_lib.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,11 +26,11 @@ 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);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
@@ -89,17 +89,21 @@ int X509V3_EXT_add_alias(int nid_to, int nid_from)
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);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ 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);
+ if (!X509V3_EXT_add(tmpext)) {
+ OPENSSL_free(tmpext);
+ return 0;
+ }
+ return 1;
}
void X509V3_EXT_cleanup(void)
@@ -267,8 +271,7 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
ext = X509V3_EXT_i2d(nid, crit, value);
if (!ext) {
- X509V3err(X509V3_F_X509V3_ADD1_I2D,
- X509V3_R_ERROR_CREATING_EXTENSION);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ERROR_CREATING_EXTENSION);
return 0;
}
@@ -292,7 +295,7 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
return 1;
m_fail:
- /* X509V3err(X509V3_F_X509V3_ADD1_I2D, ERR_R_MALLOC_FAILURE); */
+ /* ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); */
if (ret != *x)
sk_X509_EXTENSION_free(ret);
X509_EXTENSION_free(ext);
@@ -300,6 +303,6 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
err:
if (!(flags & X509V3_ADD_SILENT))
- X509V3err(X509V3_F_X509V3_ADD1_I2D, errcode);
+ ERR_raise(ERR_LIB_X509V3, errcode);
return 0;
}
diff --git a/crypto/x509v3/v3_ncons.c b/crypto/x509/v3_ncons.c
index 60cb4ceaa8f8..a51354e7fc4c 100644
--- a/crypto/x509v3/v3_ncons.c
+++ b/crypto/x509/v3_ncons.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2003-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
@@ -14,8 +14,10 @@
#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,
@@ -29,14 +31,16 @@ static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
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_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 v3_name_constraints = {
+const X509V3_EXT_METHOD ossl_v3_name_constraints = {
NID_name_constraints, 0,
ASN1_ITEM_ref(NAME_CONSTRAINTS),
0, 0, 0, 0,
@@ -139,7 +143,7 @@ static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
ptree = &ncons->excludedSubtrees;
tval.name = val->name + 9;
} else {
- X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, X509V3_R_INVALID_SYNTAX);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SYNTAX);
goto err;
}
tval.value = val->value;
@@ -158,7 +162,7 @@ static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
return ncons;
memerr:
- X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
err:
NAME_CONSTRAINTS_free(ncons);
GENERAL_SUBTREE_free(sub);
@@ -172,6 +176,8 @@ static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
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;
@@ -186,39 +192,31 @@ static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
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);
- 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;
+ /* 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)
@@ -411,7 +409,7 @@ static int cn2dnsid(ASN1_STRING *cn, unsigned char **dnsid, size_t *idlen)
int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc)
{
int r, i;
- X509_NAME *nm = X509_get_subject_name(x);
+ const X509_NAME *nm = X509_get_subject_name(x);
ASN1_STRING stmp;
GENERAL_NAME gntmp;
@@ -450,10 +448,42 @@ int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc)
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
@@ -462,16 +492,19 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
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)
+ 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 (sub->minimum || sub->maximum)
+ 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(gen, sub->base);
+ r = nc_match_single(effective_type, gen, sub->base);
if (r == X509_V_OK)
match = 2;
else if (r != X509_V_ERR_PERMITTED_VIOLATION)
@@ -485,12 +518,15 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
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)
+ 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 (sub->minimum || sub->maximum)
+ if (!nc_minmax_valid(sub))
return X509_V_ERR_SUBTREE_MINMAX;
- r = nc_match_single(gen, sub->base);
+ 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)
@@ -502,9 +538,23 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
}
-static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base)
+static int nc_match_single(int effective_type, GENERAL_NAME *gen,
+ GENERAL_NAME *base)
{
- switch (base->type) {
+ 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);
@@ -533,7 +583,7 @@ static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base)
* subset of the name.
*/
-static int nc_dn(X509_NAME *nm, X509_NAME *base)
+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)
@@ -576,6 +626,85 @@ static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
}
+/*
+ * 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;
diff --git a/crypto/x509v3/v3_pci.c b/crypto/x509/v3_pci.c
index 532d4e192fec..a931e01a9c92 100644
--- a/crypto/x509v3/v3_pci.c
+++ b/crypto/x509/v3_pci.c
@@ -1,7 +1,7 @@
/*
* 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
@@ -54,7 +54,7 @@ static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_pci =
+const X509V3_EXT_METHOD ossl_v3_pci =
{ NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
0, 0, 0, 0,
0, 0,
@@ -75,9 +75,8 @@ static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
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, "",
+ BIO_printf(out, "\n%*sPolicy Text: %.*s", indent, "",
pci->proxyPolicy->policy->length,
pci->proxyPolicy->policy->data);
return 1;
@@ -91,37 +90,35 @@ static int process_pci_value(CONF_VALUE *val,
if (strcmp(val->name, "language") == 0) {
if (*language) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
+ 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) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ 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) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
+ 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)) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_POLICY_PATH_LENGTH);
+ 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) {
+
+ if (*policy == NULL) {
*policy = ASN1_OCTET_STRING_new();
if (*policy == NULL) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
X509V3_conf_err(val);
return 0;
}
@@ -153,7 +150,7 @@ static int process_pci_value(CONF_VALUE *val,
OPENSSL_free((*policy)->data);
(*policy)->data = NULL;
(*policy)->length = 0;
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
X509V3_conf_err(val);
goto err;
}
@@ -163,7 +160,7 @@ static int process_pci_value(CONF_VALUE *val,
int n;
BIO *b = BIO_new_file(val->value + 5, "r");
if (!b) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_BIO_LIB);
X509V3_conf_err(val);
goto err;
}
@@ -179,8 +176,7 @@ static int process_pci_value(CONF_VALUE *val,
OPENSSL_free((*policy)->data);
(*policy)->data = NULL;
(*policy)->length = 0;
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
X509V3_conf_err(val);
BIO_free_all(b);
goto err;
@@ -194,7 +190,7 @@ static int process_pci_value(CONF_VALUE *val,
BIO_free_all(b);
if (n < 0) {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_BIO_LIB);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_BIO_LIB);
X509V3_conf_err(val);
goto err;
}
@@ -216,18 +212,17 @@ static int process_pci_value(CONF_VALUE *val,
OPENSSL_free((*policy)->data);
(*policy)->data = NULL;
(*policy)->length = 0;
- X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
X509V3_conf_err(val);
goto err;
}
} else {
- X509V3err(X509V3_F_PROCESS_PCI_VALUE,
- X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
X509V3_conf_err(val);
goto err;
}
@@ -254,9 +249,9 @@ static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
X509V3_conf_err(cnf);
goto err;
}
@@ -266,7 +261,7 @@ static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
sect = X509V3_get_section(ctx, cnf->name + 1);
if (!sect) {
- X509V3err(X509V3_F_R2I_PCI, X509V3_R_INVALID_SECTION);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SECTION);
X509V3_conf_err(cnf);
goto err;
}
@@ -288,20 +283,20 @@ static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
/* Language is mandatory */
if (!language) {
- X509V3err(X509V3_F_R2I_PCI,
+ 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) {
- X509V3err(X509V3_F_R2I_PCI,
+ 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) {
- X509V3err(X509V3_F_R2I_PCI, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
diff --git a/crypto/x509v3/v3_pcia.c b/crypto/x509/v3_pcia.c
index 8d6af60e5da6..7f5985f5e859 100644
--- a/crypto/x509v3/v3_pcia.c
+++ b/crypto/x509/v3_pcia.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/x509v3/v3_pcons.c b/crypto/x509/v3_pcons.c
index 24f7ff49e57c..128365f572e2 100644
--- a/crypto/x509v3/v3_pcons.c
+++ b/crypto/x509/v3_pcons.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2003-2016 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
* https://www.openssl.org/source/license.html
@@ -22,7 +22,7 @@ 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 = {
+const X509V3_EXT_METHOD ossl_v3_policy_constraints = {
NID_policy_constraints, 0,
ASN1_ITEM_ref(POLICY_CONSTRAINTS),
0, 0, 0, 0,
@@ -61,7 +61,7 @@ static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
int i;
if ((pcons = POLICY_CONSTRAINTS_new()) == NULL) {
- X509V3err(X509V3_F_V2I_POLICY_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
@@ -73,14 +73,14 @@ static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
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);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_NAME,
+ "%s", val->name);
goto err;
}
}
- if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) {
- X509V3err(X509V3_F_V2I_POLICY_CONSTRAINTS,
- X509V3_R_ILLEGAL_EMPTY_EXTENSION);
+ if (pcons->inhibitPolicyMapping == NULL
+ && pcons->requireExplicitPolicy == NULL) {
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION);
goto err;
}
diff --git a/crypto/x509v3/v3_pku.c b/crypto/x509/v3_pku.c
index 5a7e7d972516..8f7e7d681300 100644
--- a/crypto/x509v3/v3_pku.c
+++ b/crypto/x509/v3_pku.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
@@ -18,7 +18,7 @@ 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 = {
+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,
diff --git a/crypto/x509v3/v3_pmaps.c b/crypto/x509/v3_pmaps.c
index 5b6a2af0fbf6..2094e9671141 100644
--- a/crypto/x509v3/v3_pmaps.c
+++ b/crypto/x509/v3_pmaps.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2003-2016 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
* https://www.openssl.org/source/license.html
@@ -20,7 +20,7 @@ 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 = {
+const X509V3_EXT_METHOD ossl_v3_policy_mappings = {
NID_policy_mappings, 0,
ASN1_ITEM_ref(POLICY_MAPPINGS),
0, 0, 0, 0,
@@ -73,29 +73,27 @@ static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
int i;
if ((pmaps = sk_POLICY_MAPPING_new_reserve(NULL, num)) == NULL) {
- X509V3err(X509V3_F_V2I_POLICY_MAPPINGS, ERR_R_MALLOC_FAILURE);
+ 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) {
- X509V3err(X509V3_F_V2I_POLICY_MAPPINGS,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
+ 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) {
- X509V3err(X509V3_F_V2I_POLICY_MAPPINGS,
- X509V3_R_INVALID_OBJECT_IDENTIFIER);
- X509V3_conf_err(val);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER,
+ "%s", val->name);
goto err;
}
pmap = POLICY_MAPPING_new();
if (pmap == NULL) {
- X509V3err(X509V3_F_V2I_POLICY_MAPPINGS, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
pmap->issuerDomainPolicy = obj1;
diff --git a/crypto/x509v3/v3_prn.c b/crypto/x509/v3_prn.c
index f384c342acc0..1e4516a713c2 100644
--- a/crypto/x509v3/v3_prn.c
+++ b/crypto/x509/v3_prn.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
@@ -34,8 +34,11 @@ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
BIO_puts(out, "<EMPTY>\n");
}
for (i = 0; i < sk_CONF_VALUE_num(val); i++) {
- if (ml)
+ 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);
@@ -59,8 +62,6 @@ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
}
}
#endif
- if (ml)
- BIO_puts(out, "\n");
}
}
@@ -152,10 +153,15 @@ int X509V3_extensions_print(BIO *bp, const char *title,
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;
- 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)
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509/v3_purp.c
index a1aeb4e4c60b..6461189179f4 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2021 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
@@ -13,29 +13,29 @@
#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);
+#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 ca);
+ int require_ca);
static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
- int ca);
+ int require_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);
+ 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 ca);
+ int require_ca);
static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
- int ca);
+ int require_ca);
static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca);
+ int require_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);
+ 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);
@@ -53,9 +53,10 @@ static X509_PURPOSE xstandard[] = {
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",
+ {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check_purpose,
+ "Any Purpose", "any",
NULL},
- {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper,
+ {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",
@@ -72,33 +73,32 @@ static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b)
}
/*
- * 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.
+ * 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 ca)
+int X509_check_purpose(X509 *x, int id, int require_ca)
{
int idx;
const X509_PURPOSE *pt;
- x509v3_cache_extensions(x);
- if (x->ex_flags & EXFLAG_INVALID)
+ if (!ossl_x509v3_cache_extensions(x))
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);
+ return pt->check_purpose(pt, x, require_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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_PURPOSE);
return 0;
}
*p = purpose;
@@ -133,12 +133,13 @@ int X509_PURPOSE_get_by_sname(const char *sname)
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))
+ if (purpose >= X509_PURPOSE_MIN && purpose <= X509_PURPOSE_MAX)
return purpose - X509_PURPOSE_MIN;
if (xptable == NULL)
return -1;
@@ -155,9 +156,8 @@ int X509_PURPOSE_add(int id, int trust, int flags,
{
int idx;
X509_PURPOSE *ptmp;
- /*
- * This is set according to what we change: application can't set it
- */
+
+ /* 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;
@@ -166,7 +166,7 @@ int X509_PURPOSE_add(int id, int trust, int flags,
/* Need a new entry */
if (idx == -1) {
if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL) {
- X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return 0;
}
ptmp->flags = X509_PURPOSE_DYNAMIC;
@@ -178,11 +178,11 @@ int X509_PURPOSE_add(int id, int trust, int flags,
OPENSSL_free(ptmp->name);
OPENSSL_free(ptmp->sname);
}
- /* dup supplied name */
+ /* 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);
+ 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 */
@@ -199,11 +199,11 @@ int X509_PURPOSE_add(int id, int trust, int flags,
if (idx == -1) {
if (xptable == NULL
&& (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) {
- X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
- X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -219,7 +219,7 @@ int X509_PURPOSE_add(int id, int trust, int flags,
static void xptable_free(X509_PURPOSE *p)
{
- if (!p)
+ if (p == NULL)
return;
if (p->flags & X509_PURPOSE_DYNAMIC) {
if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
@@ -273,7 +273,6 @@ int X509_supported_extension(X509_EXTENSION *ex)
* 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 */
@@ -286,6 +285,7 @@ int X509_supported_extension(X509_EXTENSION *ex)
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 */
@@ -303,34 +303,49 @@ int X509_supported_extension(X509_EXTENSION *ex)
return 0;
}
-static int setup_dp(X509 *x, DIST_POINT *dp)
+/* Returns 1 on success, 0 if x is invalid, -1 on (internal) error. */
+static int setup_dp(const X509 *x, DIST_POINT *dp)
{
- X509_NAME *iname = NULL;
+ const X509_NAME *iname = NULL;
int i;
- if (dp->reasons) {
+ 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
+ } else {
dp->dp_reasons = CRLDP_ALL_REASONS;
- if (!dp->distpoint || (dp->distpoint->type != 1))
+ }
+ 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)
+ if (iname == NULL)
iname = X509_get_issuer_name(x);
-
- return DIST_POINT_set_dpname(dp->distpoint, iname);
+ 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;
@@ -338,159 +353,176 @@ static int setup_crldp(X509 *x)
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;
+ 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 *pkey, const X509 *subject)
+static int check_sig_alg_match(const EVP_PKEY *issuer_key, const X509 *subject)
{
- int pkey_sig_nid, subj_sig_nid;
+ int subj_sig_nid;
- if (pkey == NULL)
+ if (issuer_key == 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;
+ 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) && !((x)->ex_kusage & (usage)))
+ (((x)->ex_flags & EXFLAG_KUSAGE) != 0 && ((x)->ex_kusage & (usage)) == 0)
#define xku_reject(x, usage) \
- (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
+ (((x)->ex_flags & EXFLAG_XKUSAGE) != 0 && ((x)->ex_xkusage & (usage)) == 0)
#define ns_reject(x, usage) \
- (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
+ (((x)->ex_flags & EXFLAG_NSCERT) != 0 && ((x)->ex_nscert & (usage)) == 0)
-static void x509v3_cache_extensions(X509 *x)
+/*
+ * 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;
- X509_EXTENSION *ex;
int i;
+ int res;
#ifdef tsan_ld_acq
- /* fast lock-free check, see end of the function for details. */
+ /* Fast lock-free check, see end of the function for details. */
if (tsan_ld_acq((TSAN_QUALIFIER int *)&x->ex_cached))
- return;
+ return (x->ex_flags & EXFLAG_INVALID) == 0;
#endif
- CRYPTO_THREAD_write_lock(x->lock);
- if (x->ex_flags & EXFLAG_SET) {
+ 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;
+ 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 | EXFLAG_INVALID);
+ x->ex_flags |= EXFLAG_NO_FINGERPRINT;
+
+ ERR_set_mark();
/* V1 should mean no extensions ... */
- if (!X509_get_version(x))
+ if (X509_get_version(x) == X509_VERSION_1)
x->ex_flags |= EXFLAG_V1;
+
/* Handle basic constraints */
- if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &i, NULL))) {
+ 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) {
+ 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_X509V3, X509V3_R_NEGATIVE_PATHLEN);
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 ((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) {
+ if (pci->pcPathLengthConstraint != NULL)
x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
- } else
+ 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))) {
+
+ /* 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;
- } else
- x->ex_kusage = 0;
+ }
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_X509V3, 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))) {
+ 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);
@@ -498,7 +530,8 @@ static void x509v3_cache_extensions(X509 *x)
x->ex_flags |= EXFLAG_INVALID;
}
- if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &i, NULL))) {
+ /* 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
@@ -508,28 +541,40 @@ static void x509v3_cache_extensions(X509 *x)
} 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;
- /* 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 */
+
+ /* 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;
- if (!setup_crldp(x))
+
+ /* 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);
@@ -540,9 +585,10 @@ static void x509v3_cache_extensions(X509 *x)
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)
+ 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;
@@ -550,9 +596,28 @@ static void x509v3_cache_extensions(X509 *x)
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;
+ }
}
- x509_init_sig_info(x);
- x->ex_flags |= EXFLAG_SET;
+
+ /* 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);
/*
@@ -561,7 +626,19 @@ static void x509v3_cache_extensions(X509 *x)
* 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_X509V3, 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;
}
/*-
@@ -571,7 +648,7 @@ static void x509v3_cache_extensions(X509 *x)
* 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.
+ * 3 basicConstraints absent but self-signed V1.
* 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
* 5 Netscape specific CA Flags present
*/
@@ -581,14 +658,11 @@ 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 ((x->ex_flags & EXFLAG_BCONS) != 0) {
/* If basicConstraints says not a CA then say so */
- else
- return 0;
+ return (x->ex_flags & EXFLAG_CA) != 0;
} else {
- /* we support V1 roots for... uh, I don't really know why. */
+ /* We support V1 roots for... uh, I don't really know why. */
if ((x->ex_flags & V1_ROOT) == V1_ROOT)
return 3;
/*
@@ -599,14 +673,17 @@ static int check_ca(const X509 *x)
/* 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 */
+ /* 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;
+ 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)
@@ -616,31 +693,30 @@ void X509_set_proxy_pathlen(X509 *x, long l)
int X509_check_ca(X509 *x)
{
- x509v3_cache_extensions(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 */
+/* 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
+ 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 ca)
+ int require_ca)
{
if (xku_reject(x, XKU_SSL_CLIENT))
return 0;
- if (ca)
+ 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))
@@ -660,11 +736,11 @@ static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
- int ca)
+ int require_ca)
{
if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC))
return 0;
- if (ca)
+ if (require_ca)
return check_ssl_ca(x);
if (ns_reject(x, NS_SSL_SERVER))
@@ -677,11 +753,11 @@ static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
}
static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
- int ca)
+ int require_ca)
{
int ret;
- ret = check_purpose_ssl_server(xp, x, ca);
- if (!ret || ca)
+ 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))
@@ -690,16 +766,16 @@ static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
}
/* common S/MIME checks */
-static int purpose_smime(const X509 *x, int ca)
+static int purpose_smime(const X509 *x, int require_ca)
{
if (xku_reject(x, XKU_SMIME))
return 0;
- if (ca) {
+ if (require_ca) {
int ca_ret;
ca_ret = check_ca(x);
- if (!ca_ret)
+ if (ca_ret == 0)
return 0;
- /* check nsCertType if present */
+ /* Check nsCertType if present */
if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA)
return ca_ret;
else
@@ -717,11 +793,11 @@ static int purpose_smime(const X509 *x, int ca)
}
static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca)
+ int require_ca)
{
int ret;
- ret = purpose_smime(x, ca);
- if (!ret || ca)
+ ret = purpose_smime(x, require_ca);
+ if (!ret || require_ca)
return ret;
if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION))
return 0;
@@ -729,11 +805,11 @@ static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
}
static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
- int ca)
+ int require_ca)
{
int ret;
- ret = purpose_smime(x, ca);
- if (!ret || ca)
+ ret = purpose_smime(x, require_ca);
+ if (!ret || require_ca)
return ret;
if (ku_reject(x, KU_KEY_ENCIPHERMENT))
return 0;
@@ -741,9 +817,9 @@ static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
}
static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
- int ca)
+ int require_ca)
{
- if (ca) {
+ if (require_ca) {
int ca_ret;
if ((ca_ret = check_ca(x)) != 2)
return ca_ret;
@@ -759,26 +835,26 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
* 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)
+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 (ca)
+ if (require_ca)
return check_ca(x);
- /* leaf certificate is checked in OCSP_verify() */
+ /* 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 require_ca)
{
int i_ext;
/* If ca is true we must return if this is a valid CA certificate. */
- if (ca)
+ if (require_ca)
return check_ca(x);
/*
@@ -807,79 +883,76 @@ static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
return 1;
}
-static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int no_check_purpose(const X509_PURPOSE *xp, const X509 *x,
+ int require_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.
+ * 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. 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()
+ * 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 = x509_likely_issued(issuer, subject)) != X509_V_OK)
+ if ((ret = ossl_x509_likely_issued(issuer, subject)) != X509_V_OK)
return ret;
- return x509_signing_allowed(issuer, subject);
+ return ossl_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)
+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)))
+ X509_get_issuer_name(subject)) != 0)
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)
+ /* set issuer->skid and subject->akid */
+ if (!ossl_x509v3_cache_extensions(issuer)
+ || !ossl_x509v3_cache_extensions(subject))
return X509_V_ERR_UNSPECIFIED;
- if (subject->akid) {
- int ret = X509_check_akid(issuer, subject->akid);
- if (ret != X509_V_OK)
- return ret;
- }
+ 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 */
+ /* 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)
+/*-
+ * 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;
+}
- if (!akid)
+int X509_check_akid(const X509 *issuer, const AUTHORITY_KEYID *akid)
+{
+ if (akid == NULL)
return X509_V_OK;
/* Check key ids (if present) */
@@ -888,7 +961,7 @@ int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
return X509_V_ERR_AKID_SKID_MISMATCH;
/* Check serial number */
if (akid->serial &&
- ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), 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) {
@@ -909,7 +982,7 @@ int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
break;
}
}
- if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
+ 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;
@@ -918,14 +991,14 @@ int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
uint32_t X509_get_extension_flags(X509 *x)
{
/* Call for side-effect of computing hash and caching extensions */
- X509_check_purpose(x, -1, -1);
+ 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, -1) != 1)
+ if (X509_check_purpose(x, -1, 0) != 1)
return 0;
if (x->ex_flags & EXFLAG_KUSAGE)
return x->ex_kusage;
@@ -935,7 +1008,7 @@ uint32_t X509_get_key_usage(X509 *x)
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)
+ if (X509_check_purpose(x, -1, 0) != 1)
return 0;
if (x->ex_flags & EXFLAG_XKUSAGE)
return x->ex_xkusage;
@@ -945,7 +1018,7 @@ uint32_t X509_get_extended_key_usage(X509 *x)
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)
+ if (X509_check_purpose(x, -1, 0) != 1)
return NULL;
return x->skid;
}
@@ -953,7 +1026,7 @@ const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x)
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)
+ if (X509_check_purpose(x, -1, 0) != 1)
return NULL;
return (x->akid != NULL ? x->akid->keyid : NULL);
}
@@ -961,7 +1034,7 @@ const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x)
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)
+ if (X509_check_purpose(x, -1, 0) != 1)
return NULL;
return (x->akid != NULL ? x->akid->issuer : NULL);
}
@@ -969,7 +1042,7 @@ const GENERAL_NAMES *X509_get0_authority_issuer(X509 *x)
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)
+ if (X509_check_purpose(x, -1, 0) != 1)
return NULL;
return (x->akid != NULL ? x->akid->serial : NULL);
}
@@ -977,7 +1050,7 @@ const ASN1_INTEGER *X509_get0_authority_serial(X509 *x)
long X509_get_pathlen(X509 *x)
{
/* Called for side effect of caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1
+ if (X509_check_purpose(x, -1, 0) != 1
|| (x->ex_flags & EXFLAG_BCONS) == 0)
return -1;
return x->ex_pathlen;
@@ -986,7 +1059,7 @@ long X509_get_pathlen(X509 *x)
long X509_get_proxy_pathlen(X509 *x)
{
/* Called for side effect of caching extensions */
- if (X509_check_purpose(x, -1, -1) != 1
+ if (X509_check_purpose(x, -1, 0) != 1
|| (x->ex_flags & EXFLAG_PROXY) == 0)
return -1;
return x->ex_pcpathlen;
diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509/v3_san.c
index 7c32d4031d11..d4999f1fc6c7 100644
--- a/crypto/x509v3/v3_alt.c
+++ b/crypto/x509/v3_san.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
@@ -12,6 +12,7 @@
#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,
@@ -25,7 +26,7 @@ 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] = {
+const X509V3_EXT_METHOD ossl_v3_alt[3] = {
{NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
0, 0, 0, 0,
0, 0,
@@ -79,14 +80,78 @@ 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;
+ char othername[300];
+ char oline[256], *tmp;
switch (gen->type) {
case GEN_OTHERNAME:
- if (!X509V3_add_value("othername", "<unsupported>", &ret))
- return NULL;
+ 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:
@@ -124,26 +189,10 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
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;
+ 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:
@@ -157,11 +206,51 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
{
- unsigned char *p;
- int i;
+ char *tmp;
+ int nid;
+
switch (gen->type) {
case GEN_OTHERNAME:
- BIO_printf(out, "othername:<unsupported>");
+ 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:
@@ -194,20 +283,11 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
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;
- }
+ 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:
@@ -227,14 +307,14 @@ static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
int i;
if (gens == NULL) {
- X509V3err(X509V3_F_V2I_ISSUER_ALT, ERR_R_MALLOC_FAILURE);
+ 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 (!name_cmp(cnf->name, "issuer")
+ if (!ossl_v3_name_cmp(cnf->name, "issuer")
&& cnf->value && strcmp(cnf->value, "copy") == 0) {
if (!copy_issuer(ctx, gens))
goto err;
@@ -256,15 +336,15 @@ static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
{
- GENERAL_NAMES *ialt;
+ GENERAL_NAMES *ialt = NULL;
GENERAL_NAME *gen;
X509_EXTENSION *ext;
int i, num;
- if (ctx && (ctx->flags == CTX_TEST))
+ if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
return 1;
if (!ctx || !ctx->issuer_cert) {
- X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_NO_ISSUER_DETAILS);
+ 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);
@@ -272,14 +352,13 @@ static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
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);
+ 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)) {
- X509V3err(X509V3_F_COPY_ISSUER, ERR_R_MALLOC_FAILURE);
- sk_GENERAL_NAME_free(ialt);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -292,6 +371,7 @@ static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
return 1;
err:
+ sk_GENERAL_NAME_free(ialt);
return 0;
}
@@ -307,18 +387,18 @@ static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
gens = sk_GENERAL_NAME_new_reserve(NULL, num);
if (gens == NULL) {
- X509V3err(X509V3_F_V2I_SUBJECT_ALT, ERR_R_MALLOC_FAILURE);
+ 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 (!name_cmp(cnf->name, "email")
+ 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 (!name_cmp(cnf->name, "email")
+ } 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;
@@ -347,18 +427,17 @@ static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
GENERAL_NAME *gen = NULL;
int i = -1;
- if (ctx != NULL && ctx->flags == CTX_TEST)
+ if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
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;
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS);
+ return 0;
}
/* 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);
+ 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,
@@ -371,14 +450,14 @@ static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
i--;
}
if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) {
- X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
+ 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)) {
- X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
gen = NULL;
@@ -404,7 +483,7 @@ GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
gens = sk_GENERAL_NAME_new_reserve(NULL, num);
if (gens == NULL) {
- X509V3err(X509V3_F_V2I_GENERAL_NAMES, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
sk_GENERAL_NAME_free(gens);
return NULL;
}
@@ -436,7 +515,7 @@ GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
GENERAL_NAME *gen = NULL;
if (!value) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_MISSING_VALUE);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
return NULL;
}
@@ -445,7 +524,7 @@ GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
else {
gen = GENERAL_NAME_new();
if (gen == NULL) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
@@ -461,8 +540,8 @@ GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
{
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);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT,
+ "value=%s", value);
goto err;
}
gen->d.rid = obj;
@@ -475,27 +554,27 @@ GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
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);
+ 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)) {
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_DIRNAME_ERROR);
+ ERR_raise(ERR_LIB_X509V3, 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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_OTHERNAME_ERROR);
goto err;
}
break;
default:
- X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_UNSUPPORTED_TYPE);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_TYPE);
goto err;
}
@@ -503,7 +582,9 @@ GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
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);
+ ASN1_IA5STRING_free(gen->d.ia5);
+ gen->d.ia5 = NULL;
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -530,27 +611,27 @@ GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
value = cnf->value;
if (!value) {
- X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_MISSING_VALUE);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
return NULL;
}
- if (!name_cmp(name, "email"))
+ if (!ossl_v3_name_cmp(name, "email"))
type = GEN_EMAIL;
- else if (!name_cmp(name, "URI"))
+ else if (!ossl_v3_name_cmp(name, "URI"))
type = GEN_URI;
- else if (!name_cmp(name, "DNS"))
+ else if (!ossl_v3_name_cmp(name, "DNS"))
type = GEN_DNS;
- else if (!name_cmp(name, "RID"))
+ else if (!ossl_v3_name_cmp(name, "RID"))
type = GEN_RID;
- else if (!name_cmp(name, "IP"))
+ else if (!ossl_v3_name_cmp(name, "IP"))
type = GEN_IPADD;
- else if (!name_cmp(name, "dirName"))
+ else if (!ossl_v3_name_cmp(name, "dirName"))
type = GEN_DIRNAME;
- else if (!name_cmp(name, "otherName"))
+ else if (!ossl_v3_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);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_OPTION,
+ "name=%s", name);
return NULL;
}
@@ -573,16 +654,21 @@ static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
*/
ASN1_TYPE_free(gen->d.otherName->value);
if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL)
- return 0;
+ goto err;
objlen = p - value;
objtmp = OPENSSL_strndup(value, objlen);
if (objtmp == NULL)
- return 0;
+ goto err;
gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
OPENSSL_free(objtmp);
if (!gen->d.otherName->type_id)
- return 0;
+ goto err;
return 1;
+
+ err:
+ OTHERNAME_free(gen->d.otherName);
+ gen->d.otherName = NULL;
+ return 0;
}
static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
@@ -595,8 +681,8 @@ static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
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);
+ ERR_raise_data(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND,
+ "section=%s", value);
goto err;
}
/* FIXME: should allow other character types... */
diff --git a/crypto/x509v3/v3_skey.c b/crypto/x509/v3_skid.c
index c2e82045682a..18223f2ef496 100644
--- a/crypto/x509v3/v3_skey.c
+++ b/crypto/x509/v3_skid.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
@@ -15,7 +15,7 @@
static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_skey_id = {
+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,
@@ -37,7 +37,7 @@ ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
long length;
if ((oct = ASN1_OCTET_STRING_new()) == NULL) {
- X509V3err(X509V3_F_S2I_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -52,55 +52,60 @@ ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
}
-static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
- X509V3_CTX *ctx, char *str)
+ASN1_OCTET_STRING *ossl_x509_pubkey_hash(X509_PUBKEY *pubkey)
{
ASN1_OCTET_STRING *oct;
- X509_PUBKEY *pubkey;
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 (strcmp(str, "hash"))
- return s2i_ASN1_OCTET_STRING(method, ctx, str);
-
+ 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) {
- X509V3err(X509V3_F_S2I_SKEY_ID, ERR_R_MALLOC_FAILURE);
+ EVP_MD_free(md);
return NULL;
}
- if (ctx && (ctx->flags == CTX_TEST))
+ 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;
-
- 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;
- }
+ EVP_MD_free(md);
+ ASN1_OCTET_STRING_free(oct);
+ return NULL;
+}
- X509_PUBKEY_get0_param(NULL, &pk, &pklen, NULL, pubkey);
+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 (!EVP_Digest(pk, pklen, pkey_dig, &diglen, EVP_sha1(), NULL))
- goto err;
+ if (strcmp(str, "hash") != 0)
+ return s2i_ASN1_OCTET_STRING(method, ctx /* not used */, str);
- if (!ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
- X509V3err(X509V3_F_S2I_SKEY_ID, ERR_R_MALLOC_FAILURE);
- goto err;
+ 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 oct;
-
- err:
- ASN1_OCTET_STRING_free(oct);
- 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/x509v3/v3_sxnet.c b/crypto/x509/v3_sxnet.c
index 3c5508f9416c..70f5db636c4b 100644
--- a/crypto/x509v3/v3_sxnet.c
+++ b/crypto/x509/v3_sxnet.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 @@ static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *nval);
#endif
-const X509V3_EXT_METHOD v3_sxnet = {
+const X509V3_EXT_METHOD ossl_v3_sxnet = {
NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET),
0, 0, 0, 0,
0, 0,
@@ -103,8 +103,10 @@ static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
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))
+ if (!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1)) {
+ SXNET_free(sx);
return NULL;
+ }
}
return sx;
}
@@ -120,10 +122,14 @@ int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userle
ASN1_INTEGER *izone;
if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) {
- X509V3err(X509V3_F_SXNET_ADD_ID_ASC, X509V3_R_ERROR_CONVERTING_ZONE);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
return 0;
}
- return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+ if (!SXNET_add_id_INTEGER(psx, izone, user, userlen)) {
+ ASN1_INTEGER_free(izone);
+ return 0;
+ }
+ return 1;
}
/* Add an id given the zone as an unsigned long */
@@ -135,12 +141,15 @@ int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user,
if ((izone = ASN1_INTEGER_new()) == NULL
|| !ASN1_INTEGER_set(izone, lzone)) {
- X509V3err(X509V3_F_SXNET_ADD_ID_ULONG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
ASN1_INTEGER_free(izone);
return 0;
}
- return SXNET_add_id_INTEGER(psx, izone, user, userlen);
-
+ if (!SXNET_add_id_INTEGER(psx, izone, user, userlen)) {
+ ASN1_INTEGER_free(izone);
+ return 0;
+ }
+ return 1;
}
/*
@@ -153,15 +162,15 @@ int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user,
{
SXNET *sx = NULL;
SXNETID *id = NULL;
- if (!psx || !zone || !user) {
- X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER,
- X509V3_R_INVALID_NULL_ARGUMENT);
+
+ 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) {
- X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, X509V3_R_USER_TOO_LONG);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_USER_TOO_LONG);
return 0;
}
if (*psx == NULL) {
@@ -169,11 +178,12 @@ int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user,
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_DUPLICATE_ZONE_ID);
+ if (*psx == NULL)
+ SXNET_free(sx);
return 0;
}
@@ -186,14 +196,16 @@ int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user,
goto err;
if (!sk_SXNETID_push(sx->ids, id))
goto err;
+ ASN1_INTEGER_free(id->zone);
id->zone = zone;
+ *psx = sx;
return 1;
err:
- X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
SXNETID_free(id);
- SXNET_free(sx);
- *psx = NULL;
+ if (*psx == NULL)
+ SXNET_free(sx);
return 0;
}
@@ -203,7 +215,7 @@ ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone)
ASN1_OCTET_STRING *oct;
if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) {
- X509V3err(X509V3_F_SXNET_GET_ID_ASC, X509V3_R_ERROR_CONVERTING_ZONE);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
return NULL;
}
oct = SXNET_get_id_INTEGER(sx, izone);
@@ -218,7 +230,7 @@ ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone)
if ((izone = ASN1_INTEGER_new()) == NULL
|| !ASN1_INTEGER_set(izone, lzone)) {
- X509V3err(X509V3_F_SXNET_GET_ID_ULONG, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
ASN1_INTEGER_free(izone);
return NULL;
}
diff --git a/crypto/x509v3/v3_tlsf.c b/crypto/x509/v3_tlsf.c
index 7fd6ef17dbee..3a457fa57bee 100644
--- a/crypto/x509v3/v3_tlsf.c
+++ b/crypto/x509/v3_tlsf.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
@@ -10,11 +10,11 @@
#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"
+#include "x509_local.h"
static STACK_OF(CONF_VALUE) *i2v_TLS_FEATURE(const X509V3_EXT_METHOD *method,
TLS_FEATURE *tls_feature,
@@ -29,7 +29,7 @@ static_ASN1_ITEM_TEMPLATE_END(TLS_FEATURE)
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE)
-const X509V3_EXT_METHOD v3_tls_feature = {
+const X509V3_EXT_METHOD ossl_v3_tls_feature = {
NID_tlsfeature, 0,
ASN1_ITEM_ref(TLS_FEATURE),
0, 0, 0, 0,
@@ -89,14 +89,14 @@ static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
{
TLS_FEATURE *tlsf;
char *extval, *endptr;
- ASN1_INTEGER *ai;
+ ASN1_INTEGER *ai = NULL;
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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -108,7 +108,7 @@ static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
extval = val->name;
for (j = 0; j < OSSL_NELEM(tls_feature_tbl); j++)
- if (strcasecmp(extval, tls_feature_tbl[j].name) == 0)
+ if (OPENSSL_strcasecmp(extval, tls_feature_tbl[j].name) == 0)
break;
if (j < OSSL_NELEM(tls_feature_tbl))
tlsextid = tls_feature_tbl[j].num;
@@ -116,8 +116,8 @@ static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SYNTAX);
+ X509V3_conf_add_error_name_value(val);
goto err;
}
}
@@ -125,13 +125,16 @@ static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
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);
+ 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/x509v3/v3_utl.c b/crypto/x509/v3_utl.c
index eac78259fc82..56ee36d4521e 100644
--- a/crypto/x509v3/v3_utl.c
+++ b/crypto/x509/v3_utl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,15 @@
#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(X509_NAME *name,
+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 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);
@@ -44,12 +46,9 @@ static int x509v3_add_len_value(const char *name, const char *value,
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)
+ 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)
@@ -66,7 +65,7 @@ static int x509v3_add_len_value(const char *name, const char *value,
goto err;
return 1;
err:
- X509V3err(X509V3_F_X509V3_ADD_LEN_VALUE, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
if (sk_allocated) {
sk_CONF_VALUE_free(*extlist);
*extlist = NULL;
@@ -147,7 +146,7 @@ static char *bignum_to_string(const BIGNUM *bn)
len = strlen(tmp) + 3;
ret = OPENSSL_malloc(len);
if (ret == NULL) {
- X509V3err(X509V3_F_BIGNUM_TO_STRING, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
OPENSSL_free(tmp);
return NULL;
}
@@ -173,7 +172,7 @@ char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
BN_free(bntmp);
return strtmp;
}
@@ -187,7 +186,7 @@ char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
BN_free(bntmp);
return strtmp;
}
@@ -198,26 +197,29 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
ASN1_INTEGER *aint;
int isneg, ishex;
int ret;
+
if (value == NULL) {
- X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_VALUE);
return NULL;
}
bn = BN_new();
if (bn == NULL) {
- X509V3err(X509V3_F_S2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (value[0] == '-') {
value++;
isneg = 1;
- } else
+ } else {
isneg = 0;
+ }
if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
value += 2;
ishex = 1;
- } else
+ } else {
ishex = 0;
+ }
if (ishex)
ret = BN_hex2bn(&bn, value);
@@ -226,7 +228,7 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
if (!ret || value[ret]) {
BN_free(bn);
- X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_BN_DEC2BN_ERROR);
return NULL;
}
@@ -236,8 +238,7 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
return NULL;
}
if (isneg)
@@ -285,9 +286,8 @@ int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool)
return 1;
}
err:
- X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,
- X509V3_R_INVALID_BOOLEAN_STRING);
- X509V3_conf_err(value);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_BOOLEAN_STRING);
+ X509V3_conf_add_error_name_value(value);
return 0;
}
@@ -296,7 +296,7 @@ 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);
+ X509V3_conf_add_error_name_value(value);
return 0;
}
*aint = itmp;
@@ -317,10 +317,11 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
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);
+ ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
state = HDR_NAME;
@@ -336,8 +337,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
*p = 0;
ntmp = strip_spaces(q);
if (!ntmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST,
- X509V3_R_INVALID_NULL_NAME);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_EMPTY_NAME);
goto err;
}
q = p + 1;
@@ -346,11 +346,12 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
ntmp = strip_spaces(q);
q = p + 1;
if (!ntmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST,
- X509V3_R_INVALID_NULL_NAME);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_EMPTY_NAME);
+ goto err;
+ }
+ if (!X509V3_add_value(ntmp, NULL, &values)) {
goto err;
}
- X509V3_add_value(ntmp, NULL, &values);
}
break;
@@ -360,11 +361,12 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
*p = 0;
vtmp = strip_spaces(q);
if (!vtmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST,
- X509V3_R_INVALID_NULL_VALUE);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_VALUE);
+ goto err;
+ }
+ if (!X509V3_add_value(ntmp, vtmp, &values)) {
goto err;
}
- X509V3_add_value(ntmp, vtmp, &values);
ntmp = NULL;
q = p + 1;
}
@@ -375,18 +377,21 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
if (state == HDR_VALUE) {
vtmp = strip_spaces(q);
if (!vtmp) {
- X509V3err(X509V3_F_X509V3_PARSE_LIST,
- X509V3_R_INVALID_NULL_VALUE);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_VALUE);
+ goto err;
+ }
+ if (!X509V3_add_value(ntmp, vtmp, &values)) {
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);
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_EMPTY_NAME);
+ goto err;
+ }
+ if (!X509V3_add_value(ntmp, NULL, &values)) {
goto err;
}
- X509V3_add_value(ntmp, NULL, &values);
}
OPENSSL_free(linebuf);
return values;
@@ -402,18 +407,19 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
static char *strip_spaces(char *name)
{
char *p, *q;
+
/* Skip over leading spaces */
p = name;
while (*p && ossl_isspace(*p))
p++;
- if (!*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)
+ if (*p == '\0')
return NULL;
return p;
}
@@ -423,10 +429,11 @@ static char *strip_spaces(char *name)
* V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
*/
-int name_cmp(const char *name, const char *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;
@@ -489,7 +496,7 @@ STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
return ret;
}
-static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
+static STACK_OF(OPENSSL_STRING) *get_email(const X509_NAME *name,
GENERAL_NAMES *gens)
{
STACK_OF(OPENSSL_STRING) *ret = NULL;
@@ -522,9 +529,11 @@ static void str_free(OPENSSL_STRING str)
OPENSSL_free(str);
}
-static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email)
+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;
@@ -607,9 +616,10 @@ static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
skip_prefix(&pattern, &pattern_len, subject_len, flags);
if (pattern_len != subject_len)
return 0;
- while (pattern_len) {
+ while (pattern_len != 0) {
unsigned char l = *pattern;
unsigned char r = *subject;
+
/* The pattern must not contain NUL characters. */
if (l == 0)
return 0;
@@ -648,6 +658,7 @@ static int equal_email(const unsigned char *a, size_t a_len,
unsigned int unused_flags)
{
size_t i = a_len;
+
if (a_len != b_len)
return 0;
/*
@@ -704,7 +715,7 @@ static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
}
/* IDNA labels cannot match partial wildcards */
if (!allow_idna &&
- subject_len >= 4 && strncasecmp((char *)subject, "xn--", 4) == 0)
+ 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 == '*')
@@ -735,6 +746,7 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
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
@@ -763,7 +775,7 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
|| ('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)
+ && len - i >= 4 && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0)
state |= LABEL_IDNA;
state &= ~(LABEL_HYPHEN | LABEL_START);
} else if (p[i] == '.') {
@@ -776,8 +788,9 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
if ((state & LABEL_START) != 0)
return NULL;
state |= LABEL_HYPHEN;
- } else
+ } else {
return NULL;
+ }
}
/*
@@ -864,7 +877,7 @@ 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;
+ const X509_NAME *name = NULL;
int i;
int cnid = NID_undef;
int alt_type;
@@ -901,16 +914,66 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen,
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)
+ switch (gen->type) {
+ default:
continue;
- san_present = 1;
- if (check_type == GEN_EMAIL)
+ case GEN_OTHERNAME:
+ switch (OBJ_obj2nid(gen->d.otherName->type_id)) {
+ default:
+ continue;
+ case NID_id_on_SmtpUTF8Mailbox:
+ /*-
+ * https://datatracker.ietf.org/doc/html/rfc8398#section-3
+ *
+ * Due to name constraint compatibility reasons described
+ * in Section 6, SmtpUTF8Mailbox subjectAltName MUST NOT
+ * be used unless the local-part of the email address
+ * contains non-ASCII characters. When the local-part is
+ * ASCII, rfc822Name subjectAltName MUST be used instead
+ * of SmtpUTF8Mailbox. This is compatible with legacy
+ * software that supports only rfc822Name (and not
+ * SmtpUTF8Mailbox). [...]
+ *
+ * SmtpUTF8Mailbox is encoded as UTF8String.
+ *
+ * If it is not a UTF8String then that is unexpected, and
+ * we ignore the invalid SAN (neither set san_present nor
+ * consider it a candidate for equality). This does mean
+ * that the subject CN may be considered, as would be the
+ * case when the malformed SmtpUtf8Mailbox SAN is instead
+ * simply absent.
+ *
+ * When CN-ID matching is not desirable, applications can
+ * choose to turn it off, doing so is at this time a best
+ * practice.
+ */
+ if (check_type != GEN_EMAIL
+ || gen->d.otherName->value->type != V_ASN1_UTF8STRING)
+ continue;
+ alt_type = 0;
+ cstr = gen->d.otherName->value->value.utf8string;
+ break;
+ }
+ break;
+ case GEN_EMAIL:
+ if (check_type != GEN_EMAIL)
+ continue;
cstr = gen->d.rfc822Name;
- else if (check_type == GEN_DNS)
+ break;
+ case GEN_DNS:
+ if (check_type != GEN_DNS)
+ continue;
cstr = gen->d.dNSName;
- else
+ break;
+ case GEN_IPADD:
+ if (check_type != GEN_IPADD)
+ continue;
cstr = gen->d.iPAddress;
+ break;
+ }
+ san_present = 1;
/* Positive on success, negative on error! */
if ((rv = do_check_string(cstr, alt_type, equal, flags,
chk, chklen, peername)) != 0)
@@ -994,12 +1057,42 @@ int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
if (ipasc == NULL)
return -2;
- iplen = (size_t)a2i_ipadd(ipout, ipasc);
+ 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.
@@ -1013,7 +1106,7 @@ ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
/* If string contains a ':' assume IPv6 */
- iplen = a2i_ipadd(ipout, ipasc);
+ iplen = ossl_a2i_ipadd(ipout, ipasc);
if (!iplen)
return NULL;
@@ -1034,21 +1127,22 @@ ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
unsigned char ipout[32];
char *iptmp = NULL, *p;
int iplen1, iplen2;
+
p = strchr(ipasc, '/');
- if (!p)
+ if (p == NULL)
return NULL;
iptmp = OPENSSL_strdup(ipasc);
- if (!iptmp)
+ if (iptmp == NULL)
return NULL;
p = iptmp + (p - ipasc);
*p++ = 0;
- iplen1 = a2i_ipadd(ipout, iptmp);
+ iplen1 = ossl_a2i_ipadd(ipout, iptmp);
if (!iplen1)
goto err;
- iplen2 = a2i_ipadd(ipout + iplen1, p);
+ iplen2 = ossl_a2i_ipadd(ipout + iplen1, p);
OPENSSL_free(iptmp);
iptmp = NULL;
@@ -1070,7 +1164,7 @@ ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
return NULL;
}
-int a2i_ipadd(unsigned char *ipout, const char *ipasc)
+int ossl_a2i_ipadd(unsigned char *ipout, const char *ipasc)
{
/* If string contains a ':' assume IPv6 */
@@ -1119,6 +1213,7 @@ typedef struct {
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;
@@ -1141,21 +1236,19 @@ static int ipv6_from_asc(unsigned char *v6, const char *in)
if (v6stat.total == 16)
return 0;
/* More than three zeroes is an error */
- if (v6stat.zero_cnt > 3)
+ if (v6stat.zero_cnt > 3) {
return 0;
/* Can only have three zeroes if nothing else present */
- else if (v6stat.zero_cnt == 3) {
+ } 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) {
+ } 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
+ } else {
/* Can only have one zero if *not* start or end */
- {
if ((v6stat.zero_pos == 0)
|| (v6stat.zero_pos == v6stat.total))
return 0;
@@ -1174,8 +1267,9 @@ static int ipv6_from_asc(unsigned char *v6, const char *in)
memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
v6stat.tmp + v6stat.zero_pos,
v6stat.total - v6stat.zero_pos);
- } else
+ } else {
memcpy(v6, v6stat.tmp, 16);
+ }
return 1;
}
@@ -1183,6 +1277,7 @@ static int ipv6_from_asc(unsigned char *v6, const char *in)
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;
@@ -1246,6 +1341,7 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
CONF_VALUE *v;
int i, mval, spec_char, plus_char;
char *p, *type;
+
if (!nm)
return 0;
@@ -1260,7 +1356,7 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
spec_char = ((*p == ':') || (*p == ',') || (*p == '.'));
#else
spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[','])
- || (*p == os_toascii['.']));
+ || (*p == os_toascii['.']));
#endif
if (spec_char) {
p++;
@@ -1277,8 +1373,9 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
if (plus_char) {
mval = -1;
type++;
- } else
+ } else {
mval = 0;
+ }
if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
(unsigned char *)v->value, -1, -1,
mval))
diff --git a/crypto/x509v3/v3err.c b/crypto/x509/v3err.c
index 8b2918a64fff..6f38034c1afe 100644
--- a/crypto/x509v3/v3err.c
+++ b/crypto/x509/v3err.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,127 +10,10 @@
#include <openssl/err.h>
#include <openssl/x509v3err.h>
+#include "crypto/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"},
@@ -142,6 +25,7 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = {
"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),
@@ -169,6 +53,10 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = {
{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),
@@ -180,8 +68,6 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = {
{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"},
@@ -202,6 +88,8 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = {
{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),
@@ -249,13 +137,11 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = {
#endif
-int ERR_load_X509V3_strings(void)
+int ossl_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);
+ 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..6a541d7980a3 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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)
@@ -70,22 +71,23 @@ X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc)
return ret;
}
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
- X509_ATTRIBUTE *attr)
+STACK_OF(X509_ATTRIBUTE) *ossl_x509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
+ X509_ATTRIBUTE *attr)
{
X509_ATTRIBUTE *new_attr = NULL;
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,25 +97,76 @@ 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;
}
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
+ X509_ATTRIBUTE *attr)
+{
+ if (x == NULL || attr == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (*x != NULL && X509at_get_attr_by_OBJ(*x, attr->object, -1) != -1) {
+ ERR_raise(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE);
+ return NULL;
+ }
+
+ return ossl_x509at_add1_attr(x, attr);
+}
+
+STACK_OF(X509_ATTRIBUTE) *ossl_x509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x,
+ const ASN1_OBJECT *obj,
+ int type,
+ const unsigned char *bytes,
+ int len)
+{
+ X509_ATTRIBUTE *attr;
+ STACK_OF(X509_ATTRIBUTE) *ret;
+
+ attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
+ if (attr == NULL)
+ return 0;
+ ret = ossl_x509at_add1_attr(x, attr);
+ X509_ATTRIBUTE_free(attr);
+ return ret;
+}
+
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)
{
+ if (x == NULL || obj == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (*x != NULL && X509at_get_attr_by_OBJ(*x, obj, -1) != -1) {
+ ERR_raise(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE);
+ return NULL;
+ }
+
+ return ossl_x509at_add1_attr_by_OBJ(x, obj, type, bytes, len);
+}
+
+STACK_OF(X509_ATTRIBUTE) *ossl_x509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
+ int nid, int type,
+ const unsigned char *bytes,
+ int len)
+{
X509_ATTRIBUTE *attr;
STACK_OF(X509_ATTRIBUTE) *ret;
- attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
- if (!attr)
+
+ attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
+ if (attr == NULL)
return 0;
- ret = X509at_add1_attr(x, attr);
+ ret = ossl_x509at_add1_attr(x, attr);
X509_ATTRIBUTE_free(attr);
return ret;
}
@@ -123,12 +176,31 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
const unsigned char *bytes,
int len)
{
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (*x != NULL && X509at_get_attr_by_NID(*x, nid, -1) != -1) {
+ ERR_raise(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE);
+ return NULL;
+ }
+
+ return ossl_x509at_add1_attr_by_NID(x, nid, type, bytes, len);
+}
+
+STACK_OF(X509_ATTRIBUTE) *ossl_x509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
+ const char *attrname,
+ int type,
+ const unsigned char *bytes,
+ int len)
+{
X509_ATTRIBUTE *attr;
STACK_OF(X509_ATTRIBUTE) *ret;
- attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
- if (!attr)
+
+ attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
+ if (attr == NULL)
return 0;
- ret = X509at_add1_attr(x, attr);
+ ret = ossl_x509at_add1_attr(x, attr);
X509_ATTRIBUTE_free(attr);
return ret;
}
@@ -165,6 +237,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 +263,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 +281,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 +311,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 +341,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 +374,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 +404,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..f2c3a568198d 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.
+ * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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,140 @@ 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 (cert == NULL)
+ 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;
-
- return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
+ if (ret == 0) {
+ if (a->canon_enc == NULL || b->canon_enc == NULL)
+ return -2;
+ 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);
+ int i2d_ret;
/* 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;
+ i2d_ret = i2d_X509_NAME(x, NULL);
+ if (ok != NULL)
+ *ok = 0;
+ if (i2d_ret >= 0 && 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 +317,38 @@ 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 (i2d_X509_NAME(x, NULL) < 0)
+ goto end;
+
+ 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 +357,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 +367,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 +400,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 +430,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 +458,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 +478,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 +492,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 +509,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 +561,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 +569,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..37467935c997 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-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,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,24 @@ 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_DUPLICATE_ATTRIBUTE),
+ "duplicate attribute"},
+ {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 +74,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 +86,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..0434fbbc6b70 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.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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 NULL;
+ }
+ 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_trust.c
index a10d437735b8..fd77b0c6fe61 100644
--- a/crypto/x509/x509_trs.c
+++ b/crypto/x509/x509_trust.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
@@ -72,7 +72,7 @@ int X509_check_trust(X509 *x, int id, int flags)
return obj_trust(NID_anyExtendedKeyUsage, x,
flags | X509_TRUST_DO_SS_COMPAT);
idx = X509_TRUST_get_by_id(id);
- if (idx == -1)
+ if (idx < 0)
return default_trust(id, x, flags);
pt = X509_TRUST_get0(idx);
return pt->check_trust(pt, x, flags);
@@ -112,8 +112,8 @@ int X509_TRUST_get_by_id(int id)
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);
+ if (X509_TRUST_get_by_id(trust) < 0) {
+ ERR_raise(ERR_LIB_X509, X509_R_INVALID_TRUST);
return 0;
}
*t = trust;
@@ -134,9 +134,9 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
/* Get existing entry if any */
idx = X509_TRUST_get_by_id(id);
/* Need a new entry */
- if (idx == -1) {
+ if (idx < 0) {
if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) {
- X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return 0;
}
trtmp->flags = X509_TRUST_DYNAMIC;
@@ -148,7 +148,7 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
OPENSSL_free(trtmp->name);
/* dup supplied name */
if ((trtmp->name = OPENSSL_strdup(name)) == NULL) {
- X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Keep the dynamic flag of existing entry */
@@ -162,20 +162,20 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
trtmp->arg2 = arg2;
/* If its a new entry manage the dynamic table */
- if (idx == -1) {
+ if (idx < 0) {
if (trtable == NULL
&& (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) {
- X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;;
}
if (!sk_X509_TRUST_push(trtable, trtmp)) {
- X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
}
return 1;
err:
- if (idx == -1) {
+ if (idx < 0) {
OPENSSL_free(trtmp->name);
OPENSSL_free(trtmp);
}
@@ -184,7 +184,7 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
static void trtable_free(X509_TRUST *p)
{
- if (!p)
+ if (p == NULL)
return;
if (p->flags & X509_TRUST_DYNAMIC) {
if (p->flags & X509_TRUST_DYNAMIC_NAME)
@@ -220,7 +220,7 @@ 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.
+ * 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);
@@ -239,7 +239,7 @@ static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
{
- /* Call for side-effect of computing hash and caching extensions */
+ /* 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))
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index 02bde640d8e8..61d41117e2c0 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,9 +174,50 @@ 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 signature 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";
+ /*
+ * Entries must be kept consistent with include/openssl/x509_vfy.h.in
+ * and with doc/man3/X509_STORE_CTX_get_error.pod
+ */
+
default:
/* Printing an error number into a static buffer is not thread-safe */
return "unknown certificate verification error";
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..d19efeaa9919 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.
+ * 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 "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,35 +1643,34 @@ 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;
+ int i, cbcalled = 0;
/* Locate certificates with bad extensions and notify callback. */
- for (i = 1; i < sk_X509_num(ctx->chain); i++) {
+ for (i = 0; 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;
+ if ((x->ex_flags & EXFLAG_INVALID_POLICY) != 0)
+ cbcalled = 1;
+ CB_FAIL_IF((x->ex_flags & EXFLAG_INVALID_POLICY) != 0,
+ ctx, x, i, X509_V_ERR_INVALID_POLICY_EXTENSION);
+ }
+ if (!cbcalled) {
+ /* Should not be able to get here */
+ ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
+ return 0;
}
+ /* The callback ignored the error so we return success */
return 1;
}
if (ret == X509_PCY_TREE_FAILURE) {
@@ -1669,11 +1679,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 +1696,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 +1710,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 +1725,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 +1804,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 +1813,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 +1864,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 +1895,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 +1909,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 +1923,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 +1968,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 +1977,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 +2074,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 +2081,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 +2110,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 +2127,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 +2142,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 +2152,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 +2162,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 +2228,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 +2243,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 +2335,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 +2351,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 +2441,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 +2453,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 +2471,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 +2505,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 +2532,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 +2543,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 +2624,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 +2649,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 +2666,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 +2679,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 +2702,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 +2742,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 +2786,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 +2824,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 +2832,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 +2889,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 +2901,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 +2919,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 +2930,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 +2968,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 +2984,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 +3077,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 +3096,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 +3129,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 +3153,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 +3192,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 +3220,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 +3246,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 +3284,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 +3398,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 +3409,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 == 1 ? !val : -1;
}
-#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..998ce8ac1ba1 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-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
@@ -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,12 +332,13 @@ 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))
+
+ if (sk_ASN1_OBJECT_push(param->policies, policy) <= 0)
return 0;
return 1;
}
@@ -348,23 +349,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 +378,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 +406,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 +425,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 +441,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 +475,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 +508,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 +519,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 +530,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 +541,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 +552,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 +583,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,7 +595,8 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
X509_VERIFY_PARAM_free(ptmp);
}
}
- if (!sk_X509_VERIFY_PARAM_push(param_table, param))
+
+ if (sk_X509_VERIFY_PARAM_push(param_table, param) <= 0)
return 0;
return 1;
}
@@ -568,7 +604,8 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *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 +613,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..158e11a8649c 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,63 @@ 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));
+ size_t max_resp_len = (it == ASN1_ITEM_rptr(X509_CRL)) ?
+ OSSL_HTTP_DEFAULT_MAX_CRL_LEN : OSSL_HTTP_DEFAULT_MAX_RESP_LEN;
+ 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 */,
+ 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 +137,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 +178,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 +189,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 +200,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 +211,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 +219,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 +242,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 +268,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 +276,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 +315,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 +346,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 +363,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 +373,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 +384,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 +394,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 +408,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 +418,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 +428,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 +438,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 +447,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 +609,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 +620,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 +657,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 +686,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 +721,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 +750,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..eded80246df9 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-2024 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with 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;
@@ -472,21 +476,23 @@ static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname,
v = sk_ASN1_VALUE_value(intname, i);
ltmp = ASN1_item_ex_i2d(&v, in,
ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1);
- if (ltmp < 0)
- return ltmp;
+ if (ltmp < 0 || len > INT_MAX - ltmp)
+ return -1;
len += ltmp;
}
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/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/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]);